diff --git a/CMakeLists.txt b/CMakeLists.txt index 49cff1d..e5d7aa9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ enable_testing() # copy CTestCustom.cmake to build dir to disable long running tests in 'make test' configure_file(${CMAKE_SOURCE_DIR}/CTestCustom.cmake ${CMAKE_BINARY_DIR}) -project(Bitcedi) +project(Citadel) include_directories(include src external "${CMAKE_BINARY_DIR}/version") if(APPLE) @@ -51,7 +51,7 @@ else() else() set(ARCH_FLAG "-march=${ARCH}") endif() - set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Werror -Wno-error=extra -Wno-error=unused-function -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized -Wno-error=unused-result") + set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=unused-function -Wno-error=deprecated-declarations -Wno-error=sign-compare -Wno-error=strict-aliasing -Wno-error=type-limits -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized -Wno-error=unused-result") if(CMAKE_C_COMPILER_ID STREQUAL "Clang") set(WARNINGS "${WARNINGS} -Wno-error=mismatched-tags -Wno-error=null-conversion -Wno-overloaded-shift-op-parentheses -Wno-error=shift-count-overflow -Wno-error=tautological-constant-out-of-range-compare -Wno-error=unused-private-field -Wno-error=unneeded-internal-declaration -Wno-error=unused-function") else() @@ -149,4 +149,4 @@ endif() add_subdirectory(external) add_subdirectory(src) -add_subdirectory(tests) + diff --git a/README.md b/README.md index 3c83add..281eab3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Building Bitcedi +## Building Citadel ### On *nix: diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index 6d69f68..ba61a57 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -1,3 +1,9 @@ +Release notes 3.1.0-beta + +- Messages 2.0 core support +- Messages API for simplewallet +- Basic access authentication + Release notes 0.1.0 - New industrial type wallet for services: walletd diff --git a/documents/whitepapers/ctlwhitepaper.pdf b/documents/whitepapers/ctlwhitepaper.pdf new file mode 100644 index 0000000..e5c6531 Binary files /dev/null and b/documents/whitepapers/ctlwhitepaper.pdf differ diff --git a/include/IWallet.h b/include/IWallet.h index 19c46db..e84edf4 100644 --- a/include/IWallet.h +++ b/include/IWallet.h @@ -128,7 +128,7 @@ class IWallet { virtual KeyPair getAddressSpendKey(const std::string& address) const = 0; virtual KeyPair getViewKey() const = 0; virtual std::string createAddress() = 0; - virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey) = 0; + virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey, bool reset = true) = 0; virtual std::string createAddress(const Crypto::PublicKey& spendPublicKey) = 0; virtual void deleteAddress(const std::string& address) = 0; diff --git a/include/IWalletLegacy.h b/include/IWalletLegacy.h index 8360020..1f2c9d6 100644 --- a/include/IWalletLegacy.h +++ b/include/IWalletLegacy.h @@ -15,6 +15,8 @@ #include #include "CryptoNote.h" +#include "CryptoTypes.h" + namespace CryptoNote { @@ -106,6 +108,8 @@ class IWalletLegacy { virtual void removeObserver(IWalletLegacyObserver* observer) = 0; virtual void initAndGenerate(const std::string& password) = 0; + virtual void initAndGenerateDeterministic(const std::string& password) = 0; + virtual Crypto::SecretKey generateKey(const std::string& password, const Crypto::SecretKey& recovery_param = Crypto::SecretKey(), bool recover = false, bool two_random = false) = 0; virtual void initAndLoad(std::istream& source, const std::string& password) = 0; virtual void initWithKeys(const AccountKeys& accountKeys, const std::string& password) = 0; virtual void shutdown() = 0; @@ -133,13 +137,14 @@ class IWalletLegacy { virtual bool getDeposit(DepositId depositId, Deposit& deposit) = 0; virtual std::vector getTransactionsByPaymentIds(const std::vector& paymentIds) const = 0; - virtual TransactionId sendTransaction(const WalletLegacyTransfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, const std::vector& messages = std::vector()) = 0; - virtual TransactionId sendTransaction(const std::vector& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, const std::vector& messages = std::vector()) = 0; + virtual TransactionId sendTransaction(const WalletLegacyTransfer& transfer, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, const std::vector& messages = std::vector(), uint64_t ttl = 0) = 0; + virtual TransactionId sendTransaction(const std::vector& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, const std::vector& messages = std::vector(), uint64_t ttl = 0) = 0; virtual TransactionId deposit(uint32_t term, uint64_t amount, uint64_t fee, uint64_t mixIn = 0) = 0; virtual TransactionId withdrawDeposits(const std::vector& depositIds, uint64_t fee) = 0; virtual std::error_code cancelTransaction(size_t transferId) = 0; virtual void getAccountKeys(AccountKeys& keys) = 0; + virtual bool getSeed(std::string& electrum_words) = 0; }; } diff --git a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp index cabef82..a2da8fa 100644 --- a/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp +++ b/src/BlockchainExplorer/BlockchainExplorerDataBuilder.cpp @@ -216,14 +216,14 @@ bool BlockchainExplorerDataBuilder::fillTransactionDetails(const Transaction& tr if (!get_inputs_money_amount(transaction, inputsAmount)) { return false; } - transactionDetails.totalInputsAmount = core.currency().getTransactionAllInputsAmount(transaction); + transactionDetails.totalInputsAmount = core.currency().getTransactionAllInputsAmount(transaction, blockHeight); if (transaction.inputs.size() > 0 && transaction.inputs.front().type() == typeid(BaseInput)) { //It's gen transaction transactionDetails.fee = 0; transactionDetails.mixin = 0; } else { - transactionDetails.fee = core.currency().getTransactionFee(transaction); + transactionDetails.fee = core.currency().getTransactionFee(transaction, blockHeight); uint64_t mixin; if (!getMixin(transaction, mixin)) { return false; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7a16967..624af40 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,7 +2,6 @@ add_definitions(-DSTATICLIB) file(GLOB_RECURSE BlockchainExplorer BlockchainExplorer/*) file(GLOB_RECURSE Common Common/*) -file(GLOB_RECURSE ConnectivityTool ConnectivityTool/*) file(GLOB_RECURSE Crypto crypto/*) file(GLOB_RECURSE CryptoNoteCore CryptoNoteCore/* CryptoNoteConfig.h) file(GLOB_RECURSE CryptoNoteProtocol CryptoNoteProtocol/*) @@ -15,6 +14,7 @@ file(GLOB_RECURSE P2p P2p/*) file(GLOB_RECURSE Rpc Rpc/*) file(GLOB_RECURSE Serialization Serialization/*) file(GLOB_RECURSE SimpleWallet SimpleWallet/*) +file(GLOB_RECURSE Mnemonics mnemonics/*) if(MSVC) file(GLOB_RECURSE System System/* Platform/Windows/System/*) elseif(APPLE) @@ -31,8 +31,9 @@ file(GLOB_RECURSE JsonRpcServer JsonRpcServer/*) file(GLOB_RECURSE PaymentGate PaymentGate/*) file(GLOB_RECURSE PaymentGateService PaymentGateService/*) file(GLOB_RECURSE Miner Miner/*) +file(GLOB_RECURSE Mnemonics Mnemonics/*) -source_group("" FILES $${Common} ${ConnectivityTool} ${Crypto} ${CryptoNoteCore} ${CryptoNoteProtocol} ${Daemon} ${JsonRpcServer} ${Http} ${Logging} ${NodeRpcProxy} ${P2p} ${Rpc} ${Serialization} ${SimpleWallet} ${System} ${Transfers} ${Wallet} ${WalletLegacy}) +source_group("" FILES $${Common} ${Crypto} ${CryptoNoteCore} ${CryptoNoteProtocol} ${Daemon} ${JsonRpcServer} ${Http} ${Logging} ${Mnemonics} ${NodeRpcProxy} ${P2p} ${Rpc} ${Serialization} ${SimpleWallet} ${System} ${Transfers} ${Wallet} ${WalletLegacy}) add_library(BlockchainExplorer ${BlockchainExplorer}) add_library(Common ${Common}) @@ -41,6 +42,7 @@ add_library(CryptoNoteCore ${CryptoNoteCore}) add_library(Http ${Http}) add_library(InProcessNode ${InProcessNode}) add_library(Logging ${Logging}) +add_library(Mnemonics ${Mnemonics}) add_library(NodeRpcProxy ${NodeRpcProxy}) add_library(Rpc ${Rpc}) add_library(P2P ${CryptoNoteProtocol} ${P2p}) @@ -51,7 +53,6 @@ add_library(Wallet ${Wallet} ${WalletLegacy}) add_library(PaymentGate ${PaymentGate}) add_library(JsonRpcServer ${JsonRpcServer}) -add_executable(ConnectivityTool ${ConnectivityTool}) add_executable(Daemon ${Daemon}) add_executable(SimpleWallet ${SimpleWallet}) add_executable(PaymentGateService ${PaymentGateService}) @@ -61,22 +62,20 @@ if (MSVC) target_link_libraries(System ws2_32) endif () -target_link_libraries(ConnectivityTool CryptoNoteCore Common Logging Crypto P2P Rpc Http Serialization System ${Boost_LIBRARIES}) +target_link_libraries(CryptoNoteCore Common Logging Crypto P2P Rpc Http Serialization System ${Boost_LIBRARIES}) target_link_libraries(Daemon CryptoNoteCore P2P Rpc Serialization System Http Logging Common Crypto upnpc-static BlockchainExplorer ${Boost_LIBRARIES}) -target_link_libraries(SimpleWallet Wallet NodeRpcProxy Transfers Rpc Http Serialization CryptoNoteCore System Logging Common Crypto ${Boost_LIBRARIES}) +target_link_libraries(SimpleWallet Wallet NodeRpcProxy Transfers Rpc Http Serialization CryptoNoteCore System Logging Common Crypto Mnemonics ${Boost_LIBRARIES}) target_link_libraries(PaymentGateService PaymentGate JsonRpcServer Wallet NodeRpcProxy Transfers CryptoNoteCore Crypto P2P Rpc Http Serialization System Logging Common InProcessNode upnpc-static BlockchainExplorer ${Boost_LIBRARIES}) target_link_libraries(Miner CryptoNoteCore Rpc Serialization System Http Logging Common Crypto ${Boost_LIBRARIES}) add_dependencies(Rpc version) -add_dependencies(ConnectivityTool version) add_dependencies(Daemon version) add_dependencies(SimpleWallet version) add_dependencies(PaymentGateService version) add_dependencies(P2P version) -set_property(TARGET ConnectivityTool PROPERTY OUTPUT_NAME "connectivity_tool") -set_property(TARGET SimpleWallet PROPERTY OUTPUT_NAME "bitcediwallet") +set_property(TARGET SimpleWallet PROPERTY OUTPUT_NAME "citadelwallet") set_property(TARGET PaymentGateService PROPERTY OUTPUT_NAME "walletd") set_property(TARGET Miner PROPERTY OUTPUT_NAME "miner") -set_property(TARGET Daemon PROPERTY OUTPUT_NAME "bitcedid") +set_property(TARGET Daemon PROPERTY OUTPUT_NAME "citadeld") diff --git a/src/CTestCustom.cmake b/src/CTestCustom.cmake new file mode 100644 index 0000000..088261f --- /dev/null +++ b/src/CTestCustom.cmake @@ -0,0 +1,11 @@ +set(CTEST_CUSTOM_TESTS_IGNORE + CoreTests + IntegrationTestLibrary + TestGenerator + CryptoTests + IntegrationTests + NodeRpcProxyTests + PerformanceTests + TransfersTests + ) + diff --git a/src/Common/Base58.cpp b/src/Common/Base58.cpp index 127b0bf..041e602 100644 --- a/src/Common/Base58.cpp +++ b/src/Common/Base58.cpp @@ -85,15 +85,15 @@ namespace Tools uint64_t res = 0; switch (9 - size) { - case 1: res |= *data++; - case 2: res <<= 8; res |= *data++; - case 3: res <<= 8; res |= *data++; - case 4: res <<= 8; res |= *data++; - case 5: res <<= 8; res |= *data++; - case 6: res <<= 8; res |= *data++; - case 7: res <<= 8; res |= *data++; - case 8: res <<= 8; res |= *data; break; - default: assert(false); + case 1: res |= *data++; /* FALLTHRU */ + case 2: res <<= 8; res |= *data++; /* FALLTHRU */ + case 3: res <<= 8; res |= *data++; /* FALLTHRU */ + case 4: res <<= 8; res |= *data++; /* FALLTHRU */ + case 5: res <<= 8; res |= *data++; /* FALLTHRU */ + case 6: res <<= 8; res |= *data++; /* FALLTHRU */ + case 7: res <<= 8; res |= *data++; /* FALLTHRU */ + case 8: res <<= 8; res |= *data; break; + default: assert(false); } return res; diff --git a/src/Common/ConsoleHandler.cpp b/src/Common/ConsoleHandler.cpp index a9b96f7..a274c0f 100644 --- a/src/Common/ConsoleHandler.cpp +++ b/src/Common/ConsoleHandler.cpp @@ -192,9 +192,40 @@ bool ConsoleHandler::runCommand(const std::vector& cmdAndArgs) { } void ConsoleHandler::handleCommand(const std::string& cmd) { - std::vector args; - boost::split(args, cmd, boost::is_any_of(" "), boost::token_compress_on); - runCommand(args); + bool parseString = false; + std::string arg; + std::vector argList; + + for (auto ch : cmd) { + switch (ch) { + case ' ': + if (parseString) { + arg += ch; + } else if (!arg.empty()) { + argList.emplace_back(std::move(arg)); + arg.clear(); + } + break; + + case '"': + if (!arg.empty()) { + argList.emplace_back(std::move(arg)); + arg.clear(); + } + + parseString = !parseString; + break; + + default: + arg += ch; + } + } + + if (!arg.empty()) { + argList.emplace_back(std::move(arg)); + } + + runCommand(argList); } void ConsoleHandler::handlerThread() { diff --git a/src/Common/JsonValue.cpp b/src/Common/JsonValue.cpp index eecd478..0445c07 100644 --- a/src/Common/JsonValue.cpp +++ b/src/Common/JsonValue.cpp @@ -638,9 +638,8 @@ std::ostream& operator<<(std::ostream& out, const JsonValue& jsonValue) { namespace { char readChar(std::istream& in) { - char c; - - if (!(in >> c)) { + char c = static_cast(in.get()); + if (!in) { throw std::runtime_error("Unable to parse: unexpected end of stream"); } diff --git a/src/CryptoNoteConfig.h b/src/CryptoNoteConfig.h index cc3b163..cc47979 100644 --- a/src/CryptoNoteConfig.h +++ b/src/CryptoNoteConfig.h @@ -11,13 +11,13 @@ namespace CryptoNote { namespace parameters { +const uint64_t DIFFICULTY_TARGET = 240; // seconds const uint64_t CRYPTONOTE_MAX_BLOCK_NUMBER = 500000000; const size_t CRYPTONOTE_MAX_BLOCK_BLOB_SIZE = 500000000; const size_t CRYPTONOTE_MAX_TX_SIZE = 1000000000; const uint64_t CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 0xd7; // addresses start with "0xc" const size_t CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW = 6; -const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT = 60 * 60 * 2; - +const uint64_t CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT = DIFFICULTY_TARGET * 3; const size_t BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW = 30; const uint64_t MONEY_SUPPLY = UINT64_C(858986905600000000); @@ -31,10 +31,11 @@ const uint64_t COIN = UINT64_C(10000000 const uint64_t MINIMUM_FEE = UINT64_C(100000); // pow(10, 5) const uint64_t DEFAULT_DUST_THRESHOLD = UINT64_C(100000); // pow(10, 5) //const uint64_t GENESIS_BLOCK_REWARD = UINT64_C(0); +const uint64_t MAX_TX_MIXIN_SIZE = 50; -const uint64_t DIFFICULTY_TARGET = 240; // seconds const uint64_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY = 24 * 60 * 60 / DIFFICULTY_TARGET; const size_t DIFFICULTY_WINDOW = 240; // blocks +const size_t DIFFICULTY_WINDOW_V2 = 60; // blocks const size_t DIFFICULTY_CUT = 30; // timestamps to cut after sorting const size_t DIFFICULTY_LAG = 15; static_assert(2 * DIFFICULTY_CUT <= DIFFICULTY_WINDOW - 2, "Bad DIFFICULTY_WINDOW or DIFFICULTY_CUT"); @@ -44,6 +45,8 @@ const uint32_t DEPOSIT_MIN_TERM = 11000; const uint32_t DEPOSIT_MAX_TERM = 1 * 12 * 11000; const uint64_t DEPOSIT_MIN_TOTAL_RATE_FACTOR = 77000; const uint64_t DEPOSIT_MAX_TOTAL_RATE = 107; +const uint64_t DEPOSIT_MAX_TOTAL_RATE_V2 = 12; +const uint32_t DEPOSIT_MAX_TOTAL_RATE_CHANGE_HEIGHT = 196000; static_assert(DEPOSIT_MIN_TERM > 0, "Bad DEPOSIT_MIN_TERM"); static_assert(DEPOSIT_MIN_TERM <= DEPOSIT_MAX_TERM, "Bad DEPOSIT_MAX_TERM"); static_assert(DEPOSIT_MIN_TERM * DEPOSIT_MAX_TOTAL_RATE > DEPOSIT_MIN_TOTAL_RATE_FACTOR, "Bad DEPOSIT_MIN_TOTAL_RATE_FACTOR or DEPOSIT_MAX_TOTAL_RATE"); @@ -63,7 +66,10 @@ const size_t FUSION_TX_MAX_SIZE = CRYPTONOTE_BLOCK_ const size_t FUSION_TX_MIN_INPUT_COUNT = 12; const size_t FUSION_TX_MIN_IN_OUT_COUNT_RATIO = 4; -const uint64_t UPGRADE_HEIGHT = 1; +const uint32_t UPGRADE_HEIGHT_V2 = 1; +const uint32_t UPGRADE_HEIGHT_V3 = 170500; +const uint32_t UPGRADE_HEIGHT_V4 = 270000; +const uint32_t UPGRADE_HEIGHT_V5 = 314020; const unsigned UPGRADE_VOTING_THRESHOLD = 90; // percent const size_t UPGRADE_VOTING_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks const size_t UPGRADE_WINDOW = EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; // blocks @@ -77,13 +83,14 @@ const char CRYPTONOTE_POOLDATA_FILENAME[] = "poolstate.bin"; const char P2P_NET_DATA_FILENAME[] = "p2pstate.bin"; const char CRYPTONOTE_BLOCKCHAIN_INDICES_FILENAME[] = "blockchainindices.dat"; const char MINER_CONFIG_FILE_NAME[] = "miner_conf.json"; +const uint32_t EVIL_MAY_CRY_FIX = 235000; } // parameters const uint64_t START_BLOCK_REWARD = (UINT64_C(80) * parameters::COIN); const uint64_t MIN_BLOCK_REWARD = (UINT64_C(5) * parameters::COIN); const uint64_t REWARD_HALVING_INTERVAL = (UINT64_C(66000)); -const char CRYPTONOTE_NAME[] = "bitcedi"; +const char CRYPTONOTE_NAME[] = "citadel"; const char GENESIS_COINBASE_TX_HEX[] = "010601ff000180a0d9e61d029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121019e2d1a633f2a54ff1a415e0051d5a699461d9c95479f67c8568446581c2e3782"; const uint32_t GENESIS_NONCE = 70; @@ -91,6 +98,9 @@ const uint8_t TRANSACTION_VERSION_1 = 1; const uint8_t TRANSACTION_VERSION_2 = 2; const uint8_t BLOCK_MAJOR_VERSION_1 = 1; const uint8_t BLOCK_MAJOR_VERSION_2 = 2; +const uint8_t BLOCK_MAJOR_VERSION_3 = 3; +const uint8_t BLOCK_MAJOR_VERSION_4 = 4; +const uint8_t BLOCK_MAJOR_VERSION_5 = 5; const uint8_t BLOCK_MINOR_VERSION_0 = 0; const uint8_t BLOCK_MINOR_VERSION_1 = 1; @@ -104,6 +114,8 @@ const int RPC_DEFAULT_PORT = 65084; const size_t P2P_LOCAL_WHITE_PEERLIST_LIMIT = 1000; const size_t P2P_LOCAL_GRAY_PEERLIST_LIMIT = 5000; + + const size_t P2P_CONNECTION_MAX_WRITE_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB const uint32_t P2P_DEFAULT_CONNECTIONS_COUNT = 8; const size_t P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT = 70; @@ -117,9 +129,11 @@ const size_t P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT = 5000; // const char P2P_STAT_TRUSTED_PUB_KEY[] = "85ae8734f90bc1ee295ceb0ec05a49852d4dbbc9d1c27a619b5f4bdf26a0196e"; const std::initializer_list SEED_NODES = { - "seed0.bitcedi.org:55008", - "seed1.bitcedi.org:55008", - "seed2.bitcedi.org:55008" + + "94.237.61.110:55008", + "78.141.223.33:55008", + "75.119.144.113:55008", + "159.65.4.138:55008", }; struct CheckpointData { @@ -134,12 +148,16 @@ __attribute__((unused)) // You may add here other checkpoints using the following format: // {, ""}, const std::initializer_list CHECKPOINTS = { - { 100000, "0454f789f0867bf65cfc8f27ab227a68c2d4cd579a2de6d2352a3abec4a236e5" }, - { 103200, "05ebc16209bcdb97005c5cd284f2d4d669a0bf981fb4161a020247d2ce28bf64" }, + { 100000, "0454f789f0867bf65cfc8f27ab227a68c2d4cd579a2de6d2352a3abec4a236e5" }, + { 103200, "05ebc16209bcdb97005c5cd284f2d4d669a0bf981fb4161a020247d2ce28bf64" }, { 105301, "63ad1e3e08eeb3c3f05d073a4413463393014297dcc42ad39a3ee012ffd986f3" }, - + { 235674, "2c2db563461d0fb77f907bb472e321e51509cd9b959ffecd1fdbc6077c62c7e7" }, + + + }; + } // CryptoNote #define ALLOW_DEBUG_COMMANDS diff --git a/src/CryptoNoteCore/Account.cpp b/src/CryptoNoteCore/Account.cpp index 1d85763..74f08dc 100644 --- a/src/CryptoNoteCore/Account.cpp +++ b/src/CryptoNoteCore/Account.cpp @@ -5,6 +5,8 @@ #include "Account.h" #include "CryptoNoteSerialization.h" +#include "crypto/crypto.h" +#include "crypto/keccak.c" namespace CryptoNote { //----------------------------------------------------------------- @@ -21,6 +23,44 @@ void AccountBase::generate() { Crypto::generate_keys(m_keys.address.viewPublicKey, m_keys.viewSecretKey); m_creation_timestamp = time(NULL); } + +//----------------------------------------------------------------- +Crypto::SecretKey AccountBase::generate_key(const Crypto::SecretKey& recovery_key, bool recover, bool two_random) { + Crypto::SecretKey first = generate_m_keys(m_keys.address.spendPublicKey, m_keys.spendSecretKey, 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::SecretKey second; + keccak((uint8_t *)&first, sizeof(Crypto::SecretKey), (uint8_t *)&second, sizeof(Crypto::SecretKey)); + + generate_m_keys(m_keys.address.viewPublicKey, m_keys.viewSecretKey, second, two_random ? false : true); + + struct tm timestamp; + timestamp.tm_year = 2016 - 1900; // year 2016 + timestamp.tm_mon = 5 - 1; // month May + timestamp.tm_mday = 30; // 30 of May + timestamp.tm_hour = 0; + timestamp.tm_min = 0; + timestamp.tm_sec = 0; + + if (recover) + { + m_creation_timestamp = mktime(×tamp); + } + else + { + m_creation_timestamp = time(NULL); + } + return first; +} +//----------------------------------------------------------------- +void AccountBase::generateDeterministic() { + Crypto::SecretKey second; + Crypto::generate_keys(m_keys.address.spendPublicKey, m_keys.spendSecretKey); + keccak((uint8_t *)&m_keys.spendSecretKey, sizeof(Crypto::SecretKey), (uint8_t *)&second, sizeof(Crypto::SecretKey)); + Crypto::generate_deterministic_keys(m_keys.address.viewPublicKey, m_keys.viewSecretKey, second); + m_creation_timestamp = time(NULL); +} +//----------------------------------------------------------------- //----------------------------------------------------------------- const AccountKeys &AccountBase::getAccountKeys() const { return m_keys; diff --git a/src/CryptoNoteCore/Account.h b/src/CryptoNoteCore/Account.h index e675dfe..22fd4dd 100644 --- a/src/CryptoNoteCore/Account.h +++ b/src/CryptoNoteCore/Account.h @@ -19,6 +19,10 @@ namespace CryptoNote { public: AccountBase(); void generate(); + void generateDeterministic(); + + + Crypto::SecretKey generate_key(const Crypto::SecretKey& recovery_key = Crypto::SecretKey(), bool recover = false, bool two_random = false); const AccountKeys& getAccountKeys() const; void setAccountKeys(const AccountKeys& keys); diff --git a/src/CryptoNoteCore/Blockchain.cpp b/src/CryptoNoteCore/Blockchain.cpp index a19618f..058427a 100644 --- a/src/CryptoNoteCore/Blockchain.cpp +++ b/src/CryptoNoteCore/Blockchain.cpp @@ -15,6 +15,7 @@ #include "Rpc/CoreRpcServerCommandsDefinitions.h" #include "Serialization/BinarySerializationTools.h" #include "CryptoNoteTools.h" +#include "TransactionExtra.h" using namespace Logging; using namespace Common; @@ -311,7 +312,10 @@ m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), m_checkpoints(logger), -m_upgradeDetector(currency, m_blocks, BLOCK_MAJOR_VERSION_2, logger) { +m_upgradeDetectorV2(currency, m_blocks, BLOCK_MAJOR_VERSION_2, logger), +m_upgradeDetectorV3(currency, m_blocks, BLOCK_MAJOR_VERSION_3, logger), +m_upgradeDetectorV4(currency, m_blocks, BLOCK_MAJOR_VERSION_4, logger), +m_upgradeDetectorV5(currency, m_blocks, BLOCK_MAJOR_VERSION_5, logger) { m_outputs.set_deleted_key(0); m_multisignatureOutputs.set_deleted_key(0); @@ -433,7 +437,7 @@ bool Blockchain::init(const std::string& config_folder, bool load_existing) { logger(INFO, BRIGHT_WHITE) << "Blockchain not loaded, generating genesis block."; block_verification_context bvc = boost::value_initialized(); - pushBlock(m_currency.genesisBlock(), bvc); + pushBlock(m_currency.genesisBlock(), bvc, 0); if (bvc.m_verifivation_failed) { logger(ERROR, BRIGHT_RED) << "Failed to add genesis block to blockchain"; return false; @@ -449,7 +453,20 @@ bool Blockchain::init(const std::string& config_folder, bool load_existing) { } } - if (!m_upgradeDetector.init()) { + if (!m_upgradeDetectorV2.init()) { + logger(ERROR, BRIGHT_RED) << "Failed to initialize upgrade detector"; + return false; + } + + if (!m_upgradeDetectorV3.init()) { + logger(ERROR, BRIGHT_RED) << "Failed to initialize upgrade detector"; + return false; + } + if (!m_upgradeDetectorV4.init()) { + logger(ERROR, BRIGHT_RED) << "Failed to initialize upgrade detector"; + return false; + } + if (!m_upgradeDetectorV5.init()) { logger(ERROR, BRIGHT_RED) << "Failed to initialize upgrade detector"; return false; } @@ -510,7 +527,7 @@ void Blockchain::rebuildCache() { } } - interest += m_currency.calculateTotalTransactionInterest(transaction.tx); + interest += m_currency.calculateTotalTransactionInterest(transaction.tx, b); } pushToDepositIndex(block, interest); @@ -651,7 +668,8 @@ difficulty_type Blockchain::getDifficultyForNextBlock() { std::lock_guard lk(m_blockchain_lock); std::vector timestamps; std::vector commulative_difficulties; - size_t offset = m_blocks.size() - std::min(m_blocks.size(), static_cast(m_currency.difficultyBlocksCount())); + uint8_t BlockMajorVersion = m_blocks.size() >= m_upgradeDetectorV3.upgradeHeight() ? m_upgradeDetectorV3.targetVersion() : BLOCK_MAJOR_VERSION_1; + size_t offset = m_blocks.size() - std::min(m_blocks.size(), static_cast((BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount()))); if (offset == 0) { ++offset; } @@ -660,8 +678,12 @@ difficulty_type Blockchain::getDifficultyForNextBlock() { timestamps.push_back(m_blocks[offset].bl.timestamp); commulative_difficulties.push_back(m_blocks[offset].cumulative_difficulty); } +return m_currency.nextDifficulty(static_cast(m_blocks.size()), BlockMajorVersion, timestamps, commulative_difficulties); +} - return m_currency.nextDifficulty(timestamps, commulative_difficulties); +uint64_t Blockchain::getBlockTimestamp(uint32_t height) { + assert(height < m_blocks.size()); + return m_blocks[height].bl.timestamp; } uint64_t Blockchain::getCoinsInCirculation() { @@ -690,7 +712,17 @@ difficulty_type Blockchain::difficultyAtHeight(uint64_t height) { } uint8_t Blockchain::get_block_major_version_for_height(uint64_t height) const { - return height > m_upgradeDetector.upgradeHeight() ? m_upgradeDetector.targetVersion() : BLOCK_MAJOR_VERSION_1; + if (height > m_upgradeDetectorV5.upgradeHeight()) { + return m_upgradeDetectorV5.targetVersion(); + } else if (height > m_upgradeDetectorV4.upgradeHeight()) { + return m_upgradeDetectorV4.targetVersion(); + } else if (height > m_upgradeDetectorV3.upgradeHeight()) { + return m_upgradeDetectorV3.targetVersion(); + } else if (height > m_upgradeDetectorV2.upgradeHeight()) { + return m_upgradeDetectorV2.targetVersion(); + } else { + return BLOCK_MAJOR_VERSION_1; + } } bool Blockchain::rollback_blockchain_switching(std::list &original_chain, size_t rollback_height) { @@ -700,11 +732,13 @@ bool Blockchain::rollback_blockchain_switching(std::list &original_chain, popBlock(get_block_hash(m_blocks.back().bl)); } + uint32_t height = rollback_height - 1; + // return back original chain for (auto &bl : original_chain) { block_verification_context bvc = boost::value_initialized(); - bool r = pushBlock(bl, bvc); + bool r = pushBlock(bl, bvc, ++height); if (!(r && bvc.m_added_to_main_chain)) { logger(ERROR, BRIGHT_RED) << "PANIC!!! failed to add (again) block while " "chain switching during the rollback!"; @@ -730,6 +764,30 @@ bool Blockchain::switch_to_alternative_blockchain(std::list mainChainTxHashes, altChainTxHashes; + for (size_t i = m_blocks.size() - 1; i >= split_height; i--) { + Block b = m_blocks[i].bl; + std::copy(b.transactionHashes.begin(), b.transactionHashes.end(), std::inserter(mainChainTxHashes, mainChainTxHashes.end())); + } + for (auto alt_ch_iter = alt_chain.begin(); alt_ch_iter != alt_chain.end(); alt_ch_iter++) { + auto ch_ent = *alt_ch_iter; + Block b = ch_ent->second.bl; + std::copy(b.transactionHashes.begin(), b.transactionHashes.end(), std::inserter(altChainTxHashes, altChainTxHashes.end())); + } + for (auto main_ch_it = mainChainTxHashes.begin(); main_ch_it != mainChainTxHashes.end(); main_ch_it++) { + auto tx_hash = *main_ch_it; + if (std::find(altChainTxHashes.begin(), altChainTxHashes.end(), tx_hash) == altChainTxHashes.end()) { + logger(ERROR, BRIGHT_RED) << "Attempting to switch to an alternate chain, but it lacks transaction " << Common::podToHex(tx_hash) << " from main chain, rejected"; + mainChainTxHashes.clear(); + mainChainTxHashes.shrink_to_fit(); + altChainTxHashes.clear(); + altChainTxHashes.shrink_to_fit(); + return false; + } + } //disconnecting old chain std::list disconnected_chain; @@ -740,11 +798,13 @@ bool Blockchain::switch_to_alternative_blockchain(std::list(); - bool r = pushBlock(ch_ent->second.bl, bvc); + bool r = pushBlock(ch_ent->second.bl, bvc, ++height); if (!r || !bvc.m_added_to_main_chain) { logger(INFO, BRIGHT_WHITE) << "Failed to switch to alternative blockchain"; rollback_blockchain_switching(disconnected_chain, split_height); @@ -797,10 +857,13 @@ bool Blockchain::switch_to_alternative_blockchain(std::list& alt_chain, BlockEntry& bei) { std::vector timestamps; std::vector commulative_difficulties; - if (alt_chain.size() < m_currency.difficultyBlocksCount()) { + uint8_t BlockMajorVersion = m_blocks.size() >= m_upgradeDetectorV3.upgradeHeight() ? m_upgradeDetectorV3.targetVersion() : BLOCK_MAJOR_VERSION_1; + if (alt_chain.size() < (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount())) { std::lock_guard lk(m_blockchain_lock); size_t main_chain_stop_offset = alt_chain.size() ? alt_chain.front()->second.height : bei.height; - size_t main_chain_count = m_currency.difficultyBlocksCount() - std::min(m_currency.difficultyBlocksCount(), alt_chain.size()); + size_t main_chain_count = (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : + m_currency.difficultyBlocksCount()) - std::min((BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : + m_currency.difficultyBlocksCount()), alt_chain.size()); main_chain_count = std::min(main_chain_count, main_chain_stop_offset); size_t main_chain_start_offset = main_chain_stop_offset - main_chain_count; @@ -811,30 +874,30 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std: commulative_difficulties.push_back(m_blocks[main_chain_start_offset].cumulative_difficulty); } - if (!((alt_chain.size() + timestamps.size()) <= m_currency.difficultyBlocksCount())) { + if (!((alt_chain.size() + timestamps.size()) <= (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount()))) { logger(ERROR, BRIGHT_RED) << "Internal error, alt_chain.size()[" << alt_chain.size() << "] + timestamps.size()[" << timestamps.size() << - "] NOT <= m_currency.difficultyBlocksCount()[" << m_currency.difficultyBlocksCount() << ']'; return false; + "] NOT <= m_currency.difficultyBlocksCount()[" << (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount()) << ']'; return false; } for (auto it : alt_chain) { timestamps.push_back(it->second.bl.timestamp); commulative_difficulties.push_back(it->second.cumulative_difficulty); } } else { - timestamps.resize(std::min(alt_chain.size(), m_currency.difficultyBlocksCount())); - commulative_difficulties.resize(std::min(alt_chain.size(), m_currency.difficultyBlocksCount())); + timestamps.resize(std::min(alt_chain.size(), (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount()))); + commulative_difficulties.resize(std::min(alt_chain.size(), (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount()))); size_t count = 0; size_t max_i = timestamps.size() - 1; BOOST_REVERSE_FOREACH(auto it, alt_chain) { timestamps[max_i - count] = it->second.bl.timestamp; commulative_difficulties[max_i - count] = it->second.cumulative_difficulty; count++; - if (count >= m_currency.difficultyBlocksCount()) { + if (count >= (BlockMajorVersion >= BLOCK_MAJOR_VERSION_3 ? m_currency.difficultyBlocksCount2() + 1 : m_currency.difficultyBlocksCount())) { break; } } } - return m_currency.nextDifficulty(timestamps, commulative_difficulties); + return m_currency.nextDifficulty(static_cast(m_blocks.size()), BlockMajorVersion, timestamps, commulative_difficulties); } bool Blockchain::prevalidate_miner_transaction(const Block& b, uint32_t height) { @@ -1040,6 +1103,13 @@ bool Blockchain::handle_alternative_block(const Block& b, const Crypto::Hash& id bvc.m_verifivation_failed = true; return false; } + + // + TransactionExtraMergeMiningTag mmTag; + if (getMergeMiningTagFromExtra(bei.bl.baseTransaction.extra, mmTag) && bei.bl.majorVersion >= CryptoNote::BLOCK_MAJOR_VERSION_4) { + logger(ERROR, BRIGHT_RED) << "Merge mining tag was found in extra of miner transaction"; + return false; + } // Always check PoW for alternative blocks m_is_in_checkpoint_zone = false; @@ -1449,6 +1519,12 @@ bool Blockchain::checkTransactionInputs(const Transaction& tx, const Crypto::Has for (const auto& txin : tx.inputs) { assert(inputIndex < tx.signatures.size()); if (txin.type() == typeid(KeyInput)) { + uint64_t txMixin = boost::get(txin).outputIndexes.size(); + if (txMixin > CryptoNote::parameters::MAX_TX_MIXIN_SIZE) { + logger(DEBUGGING, BRIGHT_WHITE) << "Transaction << " << transactionHash << " hast too large mixin count."; + return false; + } + const KeyInput& in_to_key = boost::get(txin); if (!(!in_to_key.outputIndexes.empty())) { logger(ERROR, BRIGHT_RED) << "empty in_to_key.outputIndexes in transaction with id " << getObjectHash(tx); return false; } @@ -1696,13 +1772,15 @@ bool Blockchain::addNewBlock(const Block& bl_, block_verification_context& bvc) return false; } + uint32_t height = m_blocks.size(); + //check that block refers to chain tail if (!(bl.previousBlockHash == getTailId())) { //chain switching or wrong block bvc.m_added_to_main_chain = false; add_result = handle_alternative_block(bl, id, bvc); } else { - add_result = pushBlock(bl, bvc); + add_result = pushBlock(bl, bvc, ++height); if (add_result) { sendMessage(BlockchainMessage(NewBlockMessage(id))); } @@ -1720,15 +1798,15 @@ const Blockchain::TransactionEntry& Blockchain::transactionByIndex(TransactionIn return m_blocks[index.block].transactions[index.transaction]; } -bool Blockchain::pushBlock(const Block& blockData, block_verification_context& bvc) { +bool Blockchain::pushBlock(const Block& blockData, block_verification_context& bvc, uint32_t height) { std::vector transactions; - if (!loadTransactions(blockData, transactions)) { + if (!loadTransactions(blockData, transactions, height)) { bvc.m_verifivation_failed = true; return false; } if (!pushBlock(blockData, transactions, bvc)) { - saveTransactions(transactions); + saveTransactions(transactions, height); return false; } @@ -1753,6 +1831,13 @@ bool Blockchain::pushBlock(const Block& blockData, const std::vector= CryptoNote::BLOCK_MAJOR_VERSION_4) { + logger(ERROR, BRIGHT_RED) << "Merge mining tag was found in extra of miner transaction"; + return false; + } if (blockData.previousBlockHash != getTailId()) { logger(INFO, BRIGHT_WHITE) << @@ -1790,7 +1875,7 @@ bool Blockchain::pushBlock(const Block& blockData, const std::vector TRANSACTION_VERSION_1) { @@ -1855,7 +1942,7 @@ bool Blockchain::pushBlock(const Block& blockData, const std::vector& transactions) { +bool Blockchain::loadTransactions(const Block& block, std::vector& transactions, uint32_t height) { transactions.resize(block.transactionHashes.size()); size_t transactionSize; uint64_t fee; @@ -2393,7 +2487,7 @@ bool Blockchain::loadTransactions(const Block& block, std::vector& if (!m_tx_pool.take_tx(block.transactionHashes[i], transactions[i], transactionSize, fee)) { tx_verification_context context; for (size_t j = 0; j < i; ++j) { - if (!m_tx_pool.add_tx(transactions[i - 1 - j], context, true)) { + if (!m_tx_pool.add_tx(transactions[i - 1 - j], context, true, height)) { throw std::runtime_error("Blockchain::loadTransactions, failed to add transaction to pool"); } } @@ -2405,10 +2499,10 @@ bool Blockchain::loadTransactions(const Block& block, std::vector& return true; } -void Blockchain::saveTransactions(const std::vector& transactions) { +void Blockchain::saveTransactions(const std::vector& transactions, uint32_t height) { tx_verification_context context; for (size_t i = 0; i < transactions.size(); ++i) { - if (!m_tx_pool.add_tx(transactions[transactions.size() - 1 - i], context, true)) { + if (!m_tx_pool.add_tx(transactions[transactions.size() - 1 - i], context, true, height)) { throw std::runtime_error("Blockchain::saveTransactions, failed to add transaction to pool"); } } diff --git a/src/CryptoNoteCore/Blockchain.h b/src/CryptoNoteCore/Blockchain.h index 4871d99..ae4f9a3 100644 --- a/src/CryptoNoteCore/Blockchain.h +++ b/src/CryptoNoteCore/Blockchain.h @@ -78,6 +78,7 @@ namespace CryptoNote { Crypto::Hash getTailId(); Crypto::Hash getTailId(uint32_t& height); difficulty_type getDifficultyForNextBlock(); + uint64_t getBlockTimestamp(uint32_t height); uint64_t getCoinsInCirculation(); uint8_t get_block_major_version_for_height(uint64_t height) const; bool addNewBlock(const Block& bl_, block_verification_context& bvc); @@ -256,7 +257,11 @@ namespace CryptoNote { CryptoNote::DepositIndex m_depositIndex; TransactionMap m_transactionMap; MultisignatureOutputsContainer m_multisignatureOutputs; - UpgradeDetector m_upgradeDetector; + UpgradeDetector m_upgradeDetectorV2; + UpgradeDetector m_upgradeDetectorV3; + UpgradeDetector m_upgradeDetectorV4; + UpgradeDetector m_upgradeDetectorV5; + PaymentIdIndex m_paymentIdIndex; TimestampBlocksIndex m_timestampIndex; @@ -295,7 +300,7 @@ namespace CryptoNote { bool check_tx_outputs(const Transaction& tx) const; bool have_tx_keyimg_as_spent(const Crypto::KeyImage &key_im); const TransactionEntry& transactionByIndex(TransactionIndex index); - bool pushBlock(const Block& blockData, block_verification_context& bvc); + bool pushBlock(const Block& blockData, block_verification_context& bvc, uint32_t height); bool pushBlock(const Block& blockData, const std::vector& transactions, block_verification_context& bvc); bool pushBlock(BlockEntry& block); void popBlock(const Crypto::Hash& blockHash); @@ -307,8 +312,8 @@ namespace CryptoNote { bool storeBlockchainIndices(); bool loadBlockchainIndices(); - bool loadTransactions(const Block& block, std::vector& transactions); - void saveTransactions(const std::vector& transactions); + bool loadTransactions(const Block& block, std::vector& transactions, uint32_t height); + void saveTransactions(const std::vector& transactions, uint32_t height); void sendMessage(const BlockchainMessage& message); diff --git a/src/CryptoNoteCore/Checkpoints.cpp b/src/CryptoNoteCore/Checkpoints.cpp index d9b6cb2..c40281b 100644 --- a/src/CryptoNoteCore/Checkpoints.cpp +++ b/src/CryptoNoteCore/Checkpoints.cpp @@ -5,6 +5,7 @@ #include "Checkpoints.h" #include "Common/StringTools.h" +#include "../CryptoNoteConfig.h" using namespace Logging; @@ -61,6 +62,16 @@ bool Checkpoints::is_alternative_block_allowed(uint32_t blockchain_height, uint32_t block_height) const { if (0 == block_height) return false; + + + if (block_height < blockchain_height - CryptoNote::parameters::CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW) + { + logger(Logging::DEBUGGING, Logging::BRIGHT_WHITE) + << "An attempt of too deep reorganization: " + << blockchain_height - block_height << ", BLOCK REJECTED"; + + return false; + } auto it = m_points.upper_bound(blockchain_height); // Is blockchain_height before the first checkpoint? diff --git a/src/CryptoNoteCore/Core.cpp b/src/CryptoNoteCore/Core.cpp index 5c294ee..d0766e6 100644 --- a/src/CryptoNoteCore/Core.cpp +++ b/src/CryptoNoteCore/Core.cpp @@ -10,6 +10,7 @@ #include "../CryptoNoteConfig.h" #include "../Common/CommandLine.h" #include "../Common/Util.h" +#include "../Common/Math.h" #include "../Common/StringTools.h" #include "../crypto/crypto.h" #include "../CryptoNoteProtocol/CryptoNoteProtocolDefinitions.h" @@ -158,7 +159,7 @@ size_t core::addChain(const std::vector& chain) { getObjectHash(tx, txHash, blobSize); tx_verification_context tvc = boost::value_initialized(); - if (!handleIncomingTransaction(tx, txHash, blobSize, tvc, true)) { + if (!handleIncomingTransaction(tx, txHash, blobSize, tvc, true, get_block_height(block->getBlock()))) { logger(ERROR, BRIGHT_RED) << "core::addChain() failed to handle transaction " << txHash << " from block " << blocksCounter << "/" << chain.size(); allTransactionsAdded = false; break; @@ -205,7 +206,11 @@ bool core::handle_incoming_tx(const BinaryArray& tx_blob, tx_verification_contex } //std::cout << "!"<< tx.inputs.size() << std::endl; - return handleIncomingTransaction(tx, tx_hash, tx_blob.size(), tvc, keeped_by_block); + Crypto::Hash blockId; + uint32_t blockHeight; + bool ok = getBlockContainingTx(tx_hash, blockId, blockHeight); + if (!ok) blockHeight = this->get_current_blockchain_height(); //this assumption fails for withdrawals + return handleIncomingTransaction(tx, tx_hash, tx_blob.size(), tvc, keeped_by_block, blockHeight); } bool core::get_stat_info(core_stat_info& st_inf) { @@ -218,7 +223,22 @@ bool core::get_stat_info(core_stat_info& st_inf) { } -bool core::check_tx_semantic(const Transaction& tx, bool keeped_by_block) { +bool core::check_tx_mixin(const Transaction& tx) { + size_t inputIndex = 0; + for (const auto& txin : tx.inputs) { + assert(inputIndex < tx.signatures.size()); + if (txin.type() == typeid(KeyInput)) { + uint64_t txMixin = boost::get(txin).outputIndexes.size(); + if (txMixin > CryptoNote::parameters::MAX_TX_MIXIN_SIZE) { + logger(ERROR) << "Transaction " << getObjectHash(tx) << " has too large mixin count, rejected"; + return false; + } + } + } + return true; +} + +bool core::check_tx_semantic(const Transaction& tx, bool keeped_by_block, uint32_t &height) { if (!tx.inputs.size()) { logger(ERROR) << "tx with empty inputs, rejected for tx id= " << getObjectHash(tx); return false; @@ -240,7 +260,7 @@ bool core::check_tx_semantic(const Transaction& tx, bool keeped_by_block) { return false; } - uint64_t amount_in = m_currency.getTransactionAllInputsAmount(tx); + uint64_t amount_in = m_currency.getTransactionAllInputsAmount(tx, height); uint64_t amount_out = get_outs_money_amount(tx); if (amount_in < amount_out) { @@ -282,7 +302,7 @@ size_t core::get_blockchain_total_transactions() { // return m_blockchain.get_outs(amount, pkeys); //} -bool core::add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block) { +bool core::add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block, uint32_t height) { //Locking on m_mempool and m_blockchain closes possibility to add tx to memory pool which is already in blockchain std::lock_guard lk(m_mempool); LockedBlockchainStorage lbs(m_blockchain); @@ -297,7 +317,7 @@ bool core::add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t return true; } - return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, keeped_by_block); + return m_mempool.add_tx(tx, tx_hash, blob_size, tvc, keeped_by_block, height); } bool core::get_block_template(Block& b, const AccountPublicAddress& adr, difficulty_type& diffic, uint32_t& height, const BinaryArray& ex_nonce) { @@ -316,15 +336,32 @@ bool core::get_block_template(Block& b, const AccountPublicAddress& adr, difficu b = boost::value_initialized(); b.majorVersion = m_blockchain.get_block_major_version_for_height(height); - if (BLOCK_MAJOR_VERSION_1 == b.majorVersion) { - b.minorVersion = BLOCK_MINOR_VERSION_1; - } else if (BLOCK_MAJOR_VERSION_2 == b.majorVersion) { + if (b.majorVersion < BLOCK_MAJOR_VERSION_3) { + if (b.majorVersion == BLOCK_MAJOR_VERSION_1) { + b.minorVersion = m_currency.upgradeHeight(BLOCK_MAJOR_VERSION_2) == UpgradeDetectorBase::UNDEF_HEIGHT ? BLOCK_MINOR_VERSION_1 : BLOCK_MINOR_VERSION_0; + } else { + b.minorVersion = m_currency.upgradeHeight(BLOCK_MAJOR_VERSION_3) == UpgradeDetectorBase::UNDEF_HEIGHT ? BLOCK_MINOR_VERSION_1 : BLOCK_MINOR_VERSION_0; + } + } else { b.minorVersion = BLOCK_MINOR_VERSION_0; - } + } b.previousBlockHash = get_tail_id(); b.timestamp = time(NULL); + // Don't generate a block template with invalid timestamp + // Fix by Jagerman - https://github.com/graft-project/GraftNetwork/pull/118/commits + if(height >= m_currency.timestampCheckWindow()) { + std::vector timestamps; + for(size_t offset = height - m_currency.timestampCheckWindow(); offset < height; ++offset) { + timestamps.push_back(m_blockchain.getBlockTimestamp(offset)); + } + uint64_t median_ts = Common::medianValue(timestamps); + if (b.timestamp < median_ts) { + b.timestamp = median_ts; + } + } + median_size = m_blockchain.getCurrentCumulativeBlocksizeLimit() / 2; already_generated_coins = m_blockchain.getCoinsInCirculation(); } @@ -955,20 +992,26 @@ uint64_t core::depositInterestAtHeight(size_t height) const { return m_blockchain.depositInterestAtHeight(height); } -bool core::handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock) { +bool core::handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock, uint32_t height) { if (!check_tx_syntax(tx)) { logger(INFO) << "WRONG TRANSACTION BLOB, Failed to check tx " << txHash << " syntax, rejected"; tvc.m_verifivation_failed = true; return false; } - if (!check_tx_semantic(tx, keptByBlock)) { + if (!check_tx_mixin(tx)) { + logger(INFO) << "Transaction verification failed: mixin count for transaction " << txHash << " is too large, rejected"; + tvc.m_verifivation_failed = true; + return false; + } + + if (!check_tx_semantic(tx, keptByBlock, height)) { logger(INFO) << "WRONG TRANSACTION BLOB, Failed to check tx " << txHash << " semantic, rejected"; tvc.m_verifivation_failed = true; return false; } - bool r = add_new_tx(tx, txHash, blobSize, tvc, keptByBlock); + bool r = add_new_tx(tx, txHash, blobSize, tvc, keptByBlock, height); if (tvc.m_verifivation_failed) { if (!tvc.m_tx_fee_too_small) { logger(ERROR) << "Transaction verification failed: " << txHash; diff --git a/src/CryptoNoteCore/Core.h b/src/CryptoNoteCore/Core.h index b31fe89..d58999f 100644 --- a/src/CryptoNoteCore/Core.h +++ b/src/CryptoNoteCore/Core.h @@ -74,7 +74,7 @@ namespace CryptoNote { virtual bool getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector& transactions) override; virtual bool getOutByMSigGIndex(uint64_t amount, uint64_t gindex, MultisignatureOutput& out) override; virtual std::unique_ptr getBlock(const Crypto::Hash& blocksId) override; - virtual bool handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock) override; + virtual bool handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock, uint32_t height) override; virtual std::error_code executeLocked(const std::function& func) override; virtual bool addMessageQueue(MessageQueue& messageQueue) override; @@ -146,15 +146,18 @@ namespace CryptoNote { uint64_t depositInterestAtHeight(size_t height) const; private: - bool add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block); + bool add_new_tx(const Transaction& tx, const Crypto::Hash& tx_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block, uint32_t height); bool load_state_data(); bool parse_tx_from_blob(Transaction& tx, Crypto::Hash& tx_hash, Crypto::Hash& tx_prefix_hash, const BinaryArray& blob); bool handle_incoming_block(const Block& b, block_verification_context& bvc, bool control_miner, bool relay_block); bool check_tx_syntax(const Transaction& tx); //check correct values, amounts and all lightweight checks not related with database - bool check_tx_semantic(const Transaction& tx, bool keeped_by_block); + bool check_tx_semantic(const Transaction& tx, bool keeped_by_block, uint32_t &height); //check if tx already in memory pool or in main blockchain + bool check_tx_mixin(const Transaction& tx); + //check if the mixin is not too large + bool is_key_image_spent(const Crypto::KeyImage& key_im); diff --git a/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp b/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp index 758da84..c942e21 100644 --- a/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp +++ b/src/CryptoNoteCore/CryptoNoteFormatUtils.cpp @@ -75,6 +75,7 @@ bool constructTransaction( const std::vector& sources, const std::vector& destinations, const std::vector& messages, + uint64_t ttl, std::vector extra, Transaction& tx, uint64_t unlock_time, @@ -197,6 +198,10 @@ bool constructTransaction( } } + if (ttl != 0) { + appendTTLToExtra(tx.extra, ttl); + } + //generate ring signatures Hash tx_prefix_hash; getObjectHash(*static_cast(&tx), tx_prefix_hash); @@ -479,7 +484,17 @@ bool get_block_longhash(cn_context &context, const Block& b, Hash& res) { return false; } - cn_slow_hash(context, bd.data(), bd.size(), res); + + if (b.majorVersion >= BLOCK_MAJOR_VERSION_5) { + Crypto::Hash hash_1, hash_2; + cn_fast_hash(bd.data(), bd.size(), hash_1); + Crypto::balloon_hash(bd.data(), hash_2, bd.size(), hash_1.data, sizeof(hash_1)); + res = hash_2; + } + else { + cn_slow_hash(context, bd.data(), bd.size(), res, b.majorVersion >= 3 ? 1 : 0); + } + return true; } diff --git a/src/CryptoNoteCore/CryptoNoteFormatUtils.h b/src/CryptoNoteCore/CryptoNoteFormatUtils.h index 999cff5..81a365a 100644 --- a/src/CryptoNoteCore/CryptoNoteFormatUtils.h +++ b/src/CryptoNoteCore/CryptoNoteFormatUtils.h @@ -51,7 +51,7 @@ bool constructTransaction( const std::vector& sources, const std::vector& destinations, const std::vector& messages, - std::vector extra, Transaction& transaction, uint64_t unlock_time, Logging::ILogger& log); + uint64_t ttl, std::vector extra, Transaction& transaction, uint64_t unlock_time, Logging::ILogger& log); inline bool constructTransaction( const AccountKeys& sender_account_keys, @@ -59,7 +59,7 @@ inline bool constructTransaction( const std::vector& destinations, std::vector extra, Transaction& tx, uint64_t unlock_time, Logging::ILogger& log) { - return constructTransaction(sender_account_keys, sources, destinations, std::vector(), extra, tx, unlock_time, log); + return constructTransaction(sender_account_keys, sources, destinations, std::vector(), 0, extra, tx, unlock_time, log); } bool is_out_to_acc(const AccountKeys& acc, const KeyOutput& out_key, const Crypto::PublicKey& tx_pub_key, size_t keyIndex); diff --git a/src/CryptoNoteCore/CryptoNoteSerialization.cpp b/src/CryptoNoteCore/CryptoNoteSerialization.cpp index a27a6c8..5ad15a0 100644 --- a/src/CryptoNoteCore/CryptoNoteSerialization.cpp +++ b/src/CryptoNoteCore/CryptoNoteSerialization.cpp @@ -296,7 +296,7 @@ void serialize(MultisignatureOutput& multisignature, ISerializer& serializer) { void serializeBlockHeader(BlockHeader& header, ISerializer& serializer) { serializer(header.majorVersion, "major_version"); - if (header.majorVersion > BLOCK_MAJOR_VERSION_2) { + if (header.majorVersion > BLOCK_MAJOR_VERSION_5) { throw std::runtime_error("Wrong major version"); } diff --git a/src/CryptoNoteCore/CryptoNoteTools.cpp b/src/CryptoNoteCore/CryptoNoteTools.cpp index 3f0319f..1adf492 100644 --- a/src/CryptoNoteCore/CryptoNoteTools.cpp +++ b/src/CryptoNoteCore/CryptoNoteTools.cpp @@ -31,6 +31,19 @@ Crypto::Hash getBinaryArrayHash(const BinaryArray& binaryArray) { return hash; } +uint64_t getInputAmount(const Transaction& transaction) { + uint64_t amount = 0; + for (auto& input : transaction.inputs) { + if (input.type() == typeid(KeyInput)) { + amount += boost::get(input).amount; + } else if (input.type() == typeid(MultisignatureInput)) { + amount += boost::get(input).amount; + } + } + + return amount; +} + std::vector getInputsAmounts(const Transaction& transaction) { std::vector inputsAmounts; inputsAmounts.reserve(transaction.inputs.size()); diff --git a/src/CryptoNoteCore/CryptoNoteTools.h b/src/CryptoNoteCore/CryptoNoteTools.h index 12687a3..e867099 100644 --- a/src/CryptoNoteCore/CryptoNoteTools.h +++ b/src/CryptoNoteCore/CryptoNoteTools.h @@ -107,6 +107,7 @@ Crypto::Hash getObjectHash(const T& object) { return hash; } +uint64_t getInputAmount(const Transaction& transaction); std::vector getInputsAmounts(const Transaction& transaction); uint64_t getOutputAmount(const Transaction& transaction); void decomposeAmount(uint64_t amount, uint64_t dustThreshold, std::vector& decomposedAmounts); diff --git a/src/CryptoNoteCore/Currency.cpp b/src/CryptoNoteCore/Currency.cpp index 478bf1c..058b067 100644 --- a/src/CryptoNoteCore/Currency.cpp +++ b/src/CryptoNoteCore/Currency.cpp @@ -60,7 +60,10 @@ bool Currency::init() { } if (isTestnet()) { - m_upgradeHeight = 0; + m_upgradeHeightV2 = 0; + m_upgradeHeightV3 = 11; + m_upgradeHeightV4 = 40; + m_upgradeHeightV5 = 45; m_blocksFileName = "testnet_" + m_blocksFileName; m_blocksCacheFileName = "testnet_" + m_blocksCacheFileName; m_blockIndexesFileName = "testnet_" + m_blockIndexesFileName; @@ -98,12 +101,34 @@ bool Currency::generateGenesisBlock() { return true; } - + + uint64_t Currency::baseRewardFunction(uint64_t alreadyGeneratedCoins, uint32_t height) const { - uint64_t base_reward = START_BLOCK_REWARD >> (static_cast(height) / REWARD_HALVING_INTERVAL); + +uint64_t base_reward; + + uint64_t shift = static_cast(height) / REWARD_HALVING_INTERVAL; + base_reward = shift >= 64 ? 0 : START_BLOCK_REWARD >> shift; base_reward = (std::max)(base_reward, MIN_BLOCK_REWARD); base_reward = (std::min)(base_reward, m_moneySupply - alreadyGeneratedCoins); return base_reward; + +} + +uint32_t Currency::upgradeHeight(uint8_t majorVersion) const { + if (majorVersion == BLOCK_MAJOR_VERSION_5) { + return m_upgradeHeightV5; + } + else if (majorVersion == BLOCK_MAJOR_VERSION_4) { + return m_upgradeHeightV4; + } + else if (majorVersion == BLOCK_MAJOR_VERSION_2) { + return m_upgradeHeightV2; + } else if (majorVersion == BLOCK_MAJOR_VERSION_3) { + return m_upgradeHeightV3; + } else { + return static_cast(-1); + } } bool Currency::getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, @@ -126,11 +151,12 @@ bool Currency::getBlockReward(size_t medianSize, size_t currentBlockSize, uint64 return true; } -uint64_t Currency::calculateInterest(uint64_t amount, uint32_t term) const { +uint64_t Currency::calculateInterest(uint64_t amount, uint32_t term, uint32_t height) const { assert(m_depositMinTerm <= term && term <= m_depositMaxTerm); assert(static_cast(term)* m_depositMaxTotalRate > m_depositMinTotalRateFactor); - - uint64_t a = static_cast(term) * m_depositMaxTotalRate - m_depositMinTotalRateFactor; + + uint64_t a = static_cast(term) * (height >= depositMaxTotalRateChangeHeight() ? m_depositMaxTotalRate_v2 : m_depositMaxTotalRate) - m_depositMinTotalRateFactor; + uint64_t bHi; uint64_t bLo = mul128(amount, a, &bHi); @@ -143,13 +169,13 @@ uint64_t Currency::calculateInterest(uint64_t amount, uint32_t term) const { return interestLo; } -uint64_t Currency::calculateTotalTransactionInterest(const Transaction& tx) const { +uint64_t Currency::calculateTotalTransactionInterest(const Transaction& tx, uint32_t height) const { uint64_t interest = 0; for (const TransactionInput& input : tx.inputs) { if (input.type() == typeid(MultisignatureInput)) { const MultisignatureInput& multisignatureInput = boost::get(input); if (multisignatureInput.term != 0) { - interest += calculateInterest(multisignatureInput.amount, multisignatureInput.term); + interest += calculateInterest(multisignatureInput.amount, multisignatureInput.term, height); } } } @@ -157,7 +183,7 @@ uint64_t Currency::calculateTotalTransactionInterest(const Transaction& tx) cons return interest; } -uint64_t Currency::getTransactionInputAmount(const TransactionInput& in) const { +uint64_t Currency::getTransactionInputAmount(const TransactionInput& in, uint32_t& height) const { if (in.type() == typeid(KeyInput)) { return boost::get(in).amount; } else if (in.type() == typeid(MultisignatureInput)) { @@ -165,7 +191,7 @@ uint64_t Currency::getTransactionInputAmount(const TransactionInput& in) const { if (multisignatureInput.term == 0) { return multisignatureInput.amount; } else { - return multisignatureInput.amount + calculateInterest(multisignatureInput.amount, multisignatureInput.term); + return multisignatureInput.amount + calculateInterest(multisignatureInput.amount, multisignatureInput.term, height); } } else if (in.type() == typeid(BaseInput)) { return 0; @@ -175,37 +201,41 @@ uint64_t Currency::getTransactionInputAmount(const TransactionInput& in) const { } } -uint64_t Currency::getTransactionAllInputsAmount(const Transaction& tx) const { +uint64_t Currency::getTransactionAllInputsAmount(const Transaction& tx, uint32_t& height) const { uint64_t amount = 0; for (const auto& in : tx.inputs) { - amount += getTransactionInputAmount(in); + amount += getTransactionInputAmount(in, height); } return amount; } -bool Currency::getTransactionFee(const Transaction& tx, uint64_t & fee) const { +bool Currency::getTransactionFee(const Transaction& tx, uint64_t & fee, uint32_t& height) const { uint64_t amount_in = 0; uint64_t amount_out = 0; for (const auto& in : tx.inputs) { - amount_in += getTransactionInputAmount(in); + amount_in += getTransactionInputAmount(in, height); } for (const auto& o : tx.outputs) { amount_out += o.amount; } - if (amount_in < amount_out) { - return false; + if (amount_out > amount_in) { + if (tx.inputs.size() > 0 && tx.outputs.size() > 0 && amount_out > amount_in + parameters::MINIMUM_FEE) //take into account interest and assume that deposit txs always have min fee + fee = parameters::MINIMUM_FEE; + else + return false; } + else + fee = amount_in - amount_out; - fee = amount_in - amount_out; return true; } -uint64_t Currency::getTransactionFee(const Transaction& tx) const { +uint64_t Currency::getTransactionFee(const Transaction& tx, uint32_t height) const { uint64_t r = 0; - if (!getTransactionFee(tx, r)) { + if (!getTransactionFee(tx, r, height)) { r = 0; } return r; @@ -445,49 +475,106 @@ bool Currency::parseAmount(const std::string& str, uint64_t& amount) const { return Common::fromString(strAmount, amount); } -difficulty_type Currency::nextDifficulty(std::vector timestamps, +difficulty_type Currency::nextDifficulty(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector cumulativeDifficulties) const { - assert(m_difficultyWindow >= 2); - - if (timestamps.size() > m_difficultyWindow) { - timestamps.resize(m_difficultyWindow); - cumulativeDifficulties.resize(m_difficultyWindow); - } - - size_t length = timestamps.size(); - assert(length == cumulativeDifficulties.size()); - assert(length <= m_difficultyWindow); - if (length <= 1) { - return 1; - } - - sort(timestamps.begin(), timestamps.end()); - - size_t cutBegin, cutEnd; - assert(2 * m_difficultyCut <= m_difficultyWindow - 2); - if (length <= m_difficultyWindow - 2 * m_difficultyCut) { - cutBegin = 0; - cutEnd = length; - } else { - cutBegin = (length - (m_difficultyWindow - 2 * m_difficultyCut) + 1) / 2; - cutEnd = cutBegin + (m_difficultyWindow - 2 * m_difficultyCut); - } - assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length); - uint64_t timeSpan = timestamps[cutEnd - 1] - timestamps[cutBegin]; - if (timeSpan == 0) { - timeSpan = 1; - } - - difficulty_type totalWork = cumulativeDifficulties[cutEnd - 1] - cumulativeDifficulties[cutBegin]; - assert(totalWork > 0); - - uint64_t low, high; - low = mul128(totalWork, m_difficultyTarget, &high); - if (high != 0 || low + timeSpan - 1 < low) { - return 0; - } - - return (low + timeSpan - 1) / timeSpan; + if (blockMajorVersion >= BLOCK_MAJOR_VERSION_3) { + + // LWMA difficulty algorithm (simplified) + // Copyright (c) 2017-2018 Zawy + // MIT license http://www.opensource.org/licenses/mit-license.php + // set constants: + // N is most recent solved block. + // T= target solvetime, adjust = 0.9989^(500/N), N=int((45*(600/T)^(0.3*(600/T)^0.2) + // timestamp, cumulativedifficulties, and target are vectors of size N+1 + + const int64_t T = static_cast(m_difficultyTarget); + size_t N = CryptoNote::parameters::DIFFICULTY_WINDOW_V2; + const double_t adjust = pow(0.9989, 500 / N); + const double_t k = T * (N + 1) * adjust; + + if (timestamps.size() < 4) { + return 1; + } + // use a smaller N if timestamps and difficulies vectors are less than N+1 + if (timestamps.size() < N + 1) { + N = timestamps.size() - 1; + } + if (timestamps.size() > N + 1) { + timestamps.resize(N + 1); + } + if (cumulativeDifficulties.size() > N + 1) { + cumulativeDifficulties.resize(N + 1); + } + + int64_t L(0); + uint64_t next_D; + + for (size_t i = 1; i <= N; i++) { + if (height < CryptoNote::parameters::EVIL_MAY_CRY_FIX) { + L += (int64_t)(std::max(-7 * T, std::min(7 * T, timestamps[i] - timestamps[i - 1])) * i); + } else { + L += (int64_t)(timestamps[i] - timestamps[i - 1]) * i; + } + if (L < 1) + L = 1; + } + uint64_t low, high; + low = mul128(cumulativeDifficulties[N] - cumulativeDifficulties[0], static_cast(k), &high); + // blockchain error "Difficulty overhead" if this function returns zero + if (high != 0) { + return 0; + } + + next_D = low / L / 2; + + return next_D; + + } + else { + + assert(m_difficultyWindow >= 2); + + if (timestamps.size() > m_difficultyWindow) { + timestamps.resize(m_difficultyWindow); + cumulativeDifficulties.resize(m_difficultyWindow); + } + + size_t length = timestamps.size(); + assert(length == cumulativeDifficulties.size()); + assert(length <= m_difficultyWindow); + if (length <= 1) { + return 1; + } + + sort(timestamps.begin(), timestamps.end()); + + size_t cutBegin, cutEnd; + assert(2 * m_difficultyCut <= m_difficultyWindow - 2); + if (length <= m_difficultyWindow - 2 * m_difficultyCut) { + cutBegin = 0; + cutEnd = length; + } + else { + cutBegin = (length - (m_difficultyWindow - 2 * m_difficultyCut) + 1) / 2; + cutEnd = cutBegin + (m_difficultyWindow - 2 * m_difficultyCut); + } + assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length); + uint64_t timeSpan = timestamps[cutEnd - 1] - timestamps[cutBegin]; + if (timeSpan == 0) { + timeSpan = 1; + } + + difficulty_type totalWork = cumulativeDifficulties[cutEnd - 1] - cumulativeDifficulties[cutBegin]; + assert(totalWork > 0); + + uint64_t low, high; + low = mul128(totalWork, m_difficultyTarget, &high); + if (high != 0 || low + timeSpan - 1 < low) { + return 0; + } + + return (low + timeSpan - 1) / timeSpan; + } } bool Currency::checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, @@ -555,7 +642,9 @@ CurrencyBuilder::CurrencyBuilder(Logging::ILogger& log) : m_currency(log) { depositMaxTerm(parameters::DEPOSIT_MAX_TERM); depositMinTotalRateFactor(parameters::DEPOSIT_MIN_TOTAL_RATE_FACTOR); depositMaxTotalRate(parameters::DEPOSIT_MAX_TOTAL_RATE); - + depositMaxTotalRate_v2(parameters::DEPOSIT_MAX_TOTAL_RATE_V2); + depositMaxTotalRateChangeHeight(parameters::DEPOSIT_MAX_TOTAL_RATE_CHANGE_HEIGHT); + maxBlockSizeInitial(parameters::MAX_BLOCK_SIZE_INITIAL); maxBlockSizeGrowthSpeedNumerator(parameters::MAX_BLOCK_SIZE_GROWTH_SPEED_NUMERATOR); maxBlockSizeGrowthSpeedDenominator(parameters::MAX_BLOCK_SIZE_GROWTH_SPEED_DENOMINATOR); @@ -567,7 +656,10 @@ CurrencyBuilder::CurrencyBuilder(Logging::ILogger& log) : m_currency(log) { mempoolTxFromAltBlockLiveTime(parameters::CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME); numberOfPeriodsToForgetTxDeletedFromPool(parameters::CRYPTONOTE_NUMBER_OF_PERIODS_TO_FORGET_TX_DELETED_FROM_POOL); - upgradeHeight(parameters::UPGRADE_HEIGHT); + upgradeHeightV2(parameters::UPGRADE_HEIGHT_V2); + upgradeHeightV3(parameters::UPGRADE_HEIGHT_V3); + upgradeHeightV4(parameters::UPGRADE_HEIGHT_V4); + upgradeHeightV5(parameters::UPGRADE_HEIGHT_V5); upgradeVotingThreshold(parameters::UPGRADE_VOTING_THRESHOLD); upgradeVotingWindow(parameters::UPGRADE_VOTING_WINDOW); upgradeWindow(parameters::UPGRADE_WINDOW); diff --git a/src/CryptoNoteCore/Currency.h b/src/CryptoNoteCore/Currency.h index 350a458..b643b53 100644 --- a/src/CryptoNoteCore/Currency.h +++ b/src/CryptoNoteCore/Currency.h @@ -48,12 +48,15 @@ class Currency { size_t difficultyLag() const { return m_difficultyLag; } size_t difficultyCut() const { return m_difficultyCut; } size_t difficultyBlocksCount() const { return m_difficultyWindow + m_difficultyLag; } + size_t difficultyBlocksCount2() const { return CryptoNote::parameters::DIFFICULTY_WINDOW_V2; } uint64_t depositMinAmount() const { return m_depositMinAmount; } uint32_t depositMinTerm() const { return m_depositMinTerm; } uint32_t depositMaxTerm() const { return m_depositMaxTerm; } uint64_t depositMinTotalRateFactor() const { return m_depositMinTotalRateFactor; } uint64_t depositMaxTotalRate() const { return m_depositMaxTotalRate; } + uint64_t depositMaxTotalRate_v2() const { return m_depositMaxTotalRate_v2; } + uint32_t depositMaxTotalRateChangeHeight() const { return m_depositMaxTotalRateChangeHeight; } size_t maxBlockSizeInitial() const { return m_maxBlockSizeInitial; } uint64_t maxBlockSizeGrowthSpeedNumerator() const { return m_maxBlockSizeGrowthSpeedNumerator; } @@ -66,13 +69,13 @@ class Currency { uint64_t mempoolTxFromAltBlockLiveTime() const { return m_mempoolTxFromAltBlockLiveTime; } uint64_t numberOfPeriodsToForgetTxDeletedFromPool() const { return m_numberOfPeriodsToForgetTxDeletedFromPool; } - uint64_t upgradeHeight() const { return m_upgradeHeight; } + uint32_t upgradeHeight(uint8_t majorVersion) const; unsigned int upgradeVotingThreshold() const { return m_upgradeVotingThreshold; } - size_t upgradeVotingWindow() const { return m_upgradeVotingWindow; } - size_t upgradeWindow() const { return m_upgradeWindow; } - size_t minNumberVotingBlocks() const { return (m_upgradeVotingWindow * m_upgradeVotingThreshold + 99) / 100; } - uint64_t maxUpgradeDistance() const { return static_cast(m_upgradeWindow); } - uint64_t calculateUpgradeHeight(uint64_t voteCompleteHeight) const { return voteCompleteHeight + m_upgradeWindow; } + uint32_t upgradeVotingWindow() const { return m_upgradeVotingWindow; } + uint32_t upgradeWindow() const { return m_upgradeWindow; } + uint32_t minNumberVotingBlocks() const { return (m_upgradeVotingWindow * m_upgradeVotingThreshold + 99) / 100; } + uint32_t maxUpgradeDistance() const { return 7 * m_upgradeWindow; } + uint32_t calculateUpgradeHeight(uint32_t voteCompleteHeight) const { return voteCompleteHeight + m_upgradeWindow; } size_t fusionTxMaxSize() const { return m_fusionTxMaxSize; } size_t fusionTxMinInputCount() const { return m_fusionTxMinInputCount; } @@ -91,12 +94,12 @@ class Currency { bool getBlockReward(size_t medianSize, size_t currentBlockSize, uint64_t alreadyGeneratedCoins, uint64_t fee, uint32_t height, uint64_t& reward, int64_t& emissionChange) const; - uint64_t calculateInterest(uint64_t amount, uint32_t term) const; - uint64_t calculateTotalTransactionInterest(const Transaction& tx) const; - uint64_t getTransactionInputAmount(const TransactionInput& in) const; - uint64_t getTransactionAllInputsAmount(const Transaction& tx) const; - bool getTransactionFee(const Transaction& tx, uint64_t & fee) const; - uint64_t getTransactionFee(const Transaction& tx) const; + uint64_t calculateInterest(uint64_t amount, uint32_t term, uint32_t height) const; + uint64_t calculateTotalTransactionInterest(const Transaction& tx, uint32_t height) const; + uint64_t getTransactionInputAmount(const TransactionInput& in, uint32_t& height) const; + uint64_t getTransactionAllInputsAmount(const Transaction& tx, uint32_t& height) const; + bool getTransactionFee(const Transaction& tx, uint64_t & fee, uint32_t& height) const; + uint64_t getTransactionFee(const Transaction& tx, uint32_t height) const; size_t maxBlockCumulativeSize(uint64_t height) const; bool constructMinerTx(uint32_t height, size_t medianSize, uint64_t alreadyGeneratedCoins, size_t currentBlockSize, @@ -117,7 +120,7 @@ class Currency { std::string formatAmount(int64_t amount) const; bool parseAmount(const std::string& str, uint64_t& amount) const; - difficulty_type nextDifficulty(std::vector timestamps, std::vector cumulativeDifficulties) const; + difficulty_type nextDifficulty(uint32_t height, uint8_t blockMajorVersion, std::vector timestamps, std::vector cumulativeDifficulties) const; bool checkProofOfWork(Crypto::cn_context& context, const Block& block, difficulty_type currentDiffic, Crypto::Hash& proofOfWork) const; size_t getApproximateMaximumInputCount(size_t transactionSize, size_t outputCount, size_t mixinCount) const; @@ -164,6 +167,8 @@ class Currency { uint32_t m_depositMaxTerm; uint64_t m_depositMinTotalRateFactor; uint64_t m_depositMaxTotalRate; + uint64_t m_depositMaxTotalRate_v2; + uint32_t m_depositMaxTotalRateChangeHeight; size_t m_maxBlockSizeInitial; uint64_t m_maxBlockSizeGrowthSpeedNumerator; @@ -176,10 +181,13 @@ class Currency { uint64_t m_mempoolTxFromAltBlockLiveTime; uint64_t m_numberOfPeriodsToForgetTxDeletedFromPool; - uint64_t m_upgradeHeight; + uint32_t m_upgradeHeightV2; + uint32_t m_upgradeHeightV3; + uint32_t m_upgradeHeightV4; + uint32_t m_upgradeHeightV5; unsigned int m_upgradeVotingThreshold; - size_t m_upgradeVotingWindow; - size_t m_upgradeWindow; + uint32_t m_upgradeVotingWindow; + uint32_t m_upgradeWindow; size_t m_fusionTxMaxSize; size_t m_fusionTxMinInputCount; @@ -249,6 +257,8 @@ class CurrencyBuilder : boost::noncopyable { CurrencyBuilder& depositMaxTerm(uint32_t val) { m_currency.m_depositMaxTerm = val; return *this; } CurrencyBuilder& depositMinTotalRateFactor(uint64_t val) { m_currency.m_depositMinTotalRateFactor = val; return *this; } CurrencyBuilder& depositMaxTotalRate(uint64_t val) { m_currency.m_depositMaxTotalRate = val; return *this; } + CurrencyBuilder& depositMaxTotalRate_v2(uint64_t val) { m_currency.m_depositMaxTotalRate_v2 = val; return *this; } + CurrencyBuilder& depositMaxTotalRateChangeHeight(uint32_t val) { m_currency.m_depositMaxTotalRateChangeHeight = val; return *this; } CurrencyBuilder& maxBlockSizeInitial(size_t val) { m_currency.m_maxBlockSizeInitial = val; return *this; } CurrencyBuilder& maxBlockSizeGrowthSpeedNumerator(uint64_t val) { m_currency.m_maxBlockSizeGrowthSpeedNumerator = val; return *this; } @@ -261,7 +271,10 @@ class CurrencyBuilder : boost::noncopyable { CurrencyBuilder& mempoolTxFromAltBlockLiveTime(uint64_t val) { m_currency.m_mempoolTxFromAltBlockLiveTime = val; return *this; } CurrencyBuilder& numberOfPeriodsToForgetTxDeletedFromPool(uint64_t val) { m_currency.m_numberOfPeriodsToForgetTxDeletedFromPool = val; return *this; } - CurrencyBuilder& upgradeHeight(uint64_t val) { m_currency.m_upgradeHeight = val; return *this; } + CurrencyBuilder& upgradeHeightV2(uint64_t val) { m_currency.m_upgradeHeightV2 = val; return *this; } + CurrencyBuilder& upgradeHeightV3(uint64_t val) { m_currency.m_upgradeHeightV3 = val; return *this; } + CurrencyBuilder& upgradeHeightV4(uint64_t val) { m_currency.m_upgradeHeightV4 = val; return *this; } + CurrencyBuilder& upgradeHeightV5(uint64_t val) { m_currency.m_upgradeHeightV5 = val; return *this; } CurrencyBuilder& upgradeVotingThreshold(unsigned int val); CurrencyBuilder& upgradeVotingWindow(size_t val) { m_currency.m_upgradeVotingWindow = val; return *this; } CurrencyBuilder& upgradeWindow(size_t val); diff --git a/src/CryptoNoteCore/ICore.h b/src/CryptoNoteCore/ICore.h index 0f4793e..1315d56 100644 --- a/src/CryptoNoteCore/ICore.h +++ b/src/CryptoNoteCore/ICore.h @@ -101,7 +101,7 @@ class ICore { virtual bool getTransactionsByPaymentId(const Crypto::Hash& paymentId, std::vector& transactions) = 0; virtual std::unique_ptr getBlock(const Crypto::Hash& blocksId) = 0; - virtual bool handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock) = 0; + virtual bool handleIncomingTransaction(const Transaction& tx, const Crypto::Hash& txHash, size_t blobSize, tx_verification_context& tvc, bool keptByBlock, uint32_t height) = 0; virtual std::error_code executeLocked(const std::function& func) = 0; virtual bool addMessageQueue(MessageQueue& messageQueue) = 0; diff --git a/src/CryptoNoteCore/SwappedMap.h b/src/CryptoNoteCore/SwappedMap.h index 8e005f8..28aa2d6 100644 --- a/src/CryptoNoteCore/SwappedMap.h +++ b/src/CryptoNoteCore/SwappedMap.h @@ -183,7 +183,7 @@ template bool SwappedMap::open(const std::string& it } template void SwappedMap::close() { - std::cout << "SwappedMap cache hits: " << m_cacheHits << ", misses: " << m_cacheMisses << " (" << std::fixed << std::setprecision(2) << static_cast(m_cacheMisses) / (m_cacheHits + m_cacheMisses) * 100 << "%)" << std::endl; + //std::cout << "SwappedMap cache hits: " << m_cacheHits << ", misses: " << m_cacheMisses << " (" << std::fixed << std::setprecision(2) << static_cast(m_cacheMisses) / (m_cacheHits + m_cacheMisses) * 100 << "%)" << std::endl; } template uint64_t SwappedMap::size() const { diff --git a/src/CryptoNoteCore/TransactionExtra.cpp b/src/CryptoNoteCore/TransactionExtra.cpp index 7bd67ef..d986a0f 100644 --- a/src/CryptoNoteCore/TransactionExtra.cpp +++ b/src/CryptoNoteCore/TransactionExtra.cpp @@ -9,6 +9,7 @@ #include "Common/MemoryInputStream.h" #include "Common/StreamTools.h" #include "Common/StringTools.h" +#include "Common/Varint.h" #include "CryptoNoteTools.h" #include "Serialization/BinaryOutputStreamSerializer.h" #include "Serialization/BinaryInputStreamSerializer.h" @@ -81,6 +82,15 @@ bool parseTransactionExtra(const std::vector &transactionExtra, std::ve transactionExtraFields.push_back(message); break; } + + case TX_EXTRA_TTL: { + uint8_t size; + readVarint(iss, size); + TransactionExtraTTL ttl; + readVarint(iss, ttl.ttl); + transactionExtraFields.push_back(ttl); + break; + } } } } catch (std::exception &) { @@ -119,6 +129,11 @@ struct ExtraSerializerVisitor : public boost::static_visitor { bool operator()(const tx_extra_message& t) { return append_message_to_extra(extra, t); } + + bool operator()(const TransactionExtraTTL& t) { + appendTTLToExtra(extra, t.ttl); + return true; + } }; bool writeTransactionExtra(std::vector& tx_extra, const std::vector& tx_extra_fields) { @@ -221,6 +236,16 @@ std::vector get_messages_from_extra(const std::vector &ext return result; } +void appendTTLToExtra(std::vector& tx_extra, uint64_t ttl) { + std::string ttlData = Tools::get_varint_data(ttl); + std::string extraFieldSize = Tools::get_varint_data(ttlData.size()); + + tx_extra.reserve(tx_extra.size() + 1 + extraFieldSize.size() + ttlData.size()); + tx_extra.push_back(TX_EXTRA_TTL); + std::copy(extraFieldSize.begin(), extraFieldSize.end(), std::back_inserter(tx_extra)); + std::copy(ttlData.begin(), ttlData.end(), std::back_inserter(tx_extra)); +} + void setPaymentIdToTransactionExtraNonce(std::vector& extra_nonce, const Hash& payment_id) { extra_nonce.clear(); extra_nonce.push_back(TX_EXTRA_NONCE_PAYMENT_ID); diff --git a/src/CryptoNoteCore/TransactionExtra.h b/src/CryptoNoteCore/TransactionExtra.h index fa5f2f2..5045da3 100644 --- a/src/CryptoNoteCore/TransactionExtra.h +++ b/src/CryptoNoteCore/TransactionExtra.h @@ -19,6 +19,7 @@ #define TX_EXTRA_NONCE 0x02 #define TX_EXTRA_MERGE_MINING_TAG 0x03 #define TX_EXTRA_MESSAGE_TAG 0x04 +#define TX_EXTRA_TTL 0x05 #define TX_EXTRA_NONCE_PAYMENT_ID 0x00 @@ -52,11 +53,15 @@ struct tx_extra_message { bool serialize(ISerializer& serializer); }; +struct TransactionExtraTTL { + uint64_t ttl; +}; + // tx_extra_field format, except tx_extra_padding and tx_extra_pub_key: // varint tag; // varint size; // varint data[]; -typedef boost::variant TransactionExtraField; +typedef boost::variant TransactionExtraField; @@ -81,8 +86,10 @@ bool addExtraNonceToTransactionExtra(std::vector& tx_extra, const Binar void setPaymentIdToTransactionExtraNonce(BinaryArray& extra_nonce, const Crypto::Hash& payment_id); bool getPaymentIdFromTransactionExtraNonce(const BinaryArray& extra_nonce, Crypto::Hash& payment_id); bool appendMergeMiningTagToExtra(std::vector& tx_extra, const TransactionExtraMergeMiningTag& mm_tag); +bool getMergeMiningTagFromExtra(const std::vector& tx_extra, TransactionExtraMergeMiningTag& mm_tag); bool append_message_to_extra(std::vector& tx_extra, const tx_extra_message& message); std::vector get_messages_from_extra(const std::vector& extra, const Crypto::PublicKey &txkey, const Crypto::SecretKey *recepient_secret_key); +void appendTTLToExtra(std::vector& tx_extra, uint64_t ttl); bool createTxExtraWithPaymentId(const std::string& paymentIdString, std::vector& extra); //returns false if payment id is not found or parse error diff --git a/src/CryptoNoteCore/TransactionPool.cpp b/src/CryptoNoteCore/TransactionPool.cpp index 594499e..310cf18 100644 --- a/src/CryptoNoteCore/TransactionPool.cpp +++ b/src/CryptoNoteCore/TransactionPool.cpp @@ -22,6 +22,7 @@ #include "CryptoNoteFormatUtils.h" #include "CryptoNoteTools.h" #include "CryptoNoteConfig.h" +#include "TransactionExtra.h" using namespace Logging; @@ -96,16 +97,18 @@ namespace CryptoNote { m_timeProvider(timeProvider), m_txCheckInterval(60, timeProvider), m_fee_index(boost::get<1>(m_transactions)), - logger(log, "txpool") { + logger(log, "txpool"), + m_paymentIdIndex(), + m_timestampIndex() { } //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(const Transaction &tx, /*const Crypto::Hash& tx_prefix_hash,*/ const Crypto::Hash &id, size_t blobSize, tx_verification_context& tvc, bool keptByBlock) { + bool tx_memory_pool::add_tx(const Transaction &tx, /*const Crypto::Hash& tx_prefix_hash,*/ const Crypto::Hash &id, size_t blobSize, tx_verification_context& tvc, bool keptByBlock, uint32_t height) { if (!check_inputs_types_supported(tx)) { tvc.m_verifivation_failed = true; return false; } - uint64_t inputs_amount = m_currency.getTransactionAllInputsAmount(tx); + uint64_t inputs_amount = m_currency.getTransactionAllInputsAmount(tx, height); uint64_t outputs_amount = get_outs_money_amount(tx); if (outputs_amount > inputs_amount) { @@ -115,9 +118,16 @@ namespace CryptoNote { return false; } + std::vector txExtraFields; + parseTransactionExtra(tx.extra, txExtraFields); + TransactionExtraTTL ttl; + if (!findTransactionExtraFieldByType(txExtraFields, ttl)) { + ttl.ttl = 0; + } + const uint64_t fee = inputs_amount - outputs_amount; bool isFusionTransaction = fee == 0 && m_currency.isFusionTransaction(tx, blobSize); - if (!keptByBlock && !isFusionTransaction && fee < m_currency.minimumFee()) { + if (!keptByBlock && !isFusionTransaction && ttl.ttl == 0 && fee < m_currency.minimumFee()) { logger(INFO) << "transaction fee is not enough: " << m_currency.formatAmount(fee) << ", minimum fee: " << m_currency.formatAmount(m_currency.minimumFee()); tvc.m_verifivation_failed = true; @@ -125,6 +135,25 @@ namespace CryptoNote { return false; } + if (ttl.ttl != 0 && !keptByBlock) { + uint64_t now = static_cast(time(nullptr)); + if (ttl.ttl <= now) { + logger(WARNING, BRIGHT_YELLOW) << "Transaction TTL has already expired: tx = " << id << ", ttl = " << ttl.ttl; + tvc.m_verifivation_failed = true; + return false; + } else if (ttl.ttl - now > m_currency.mempoolTxLiveTime() + m_currency.blockFutureTimeLimit()) { + logger(WARNING, BRIGHT_YELLOW) << "Transaction TTL is out of range: tx = " << id << ", ttl = " << ttl.ttl; + tvc.m_verifivation_failed = true; + return false; + } + + if (fee != 0) { + logger(WARNING, BRIGHT_YELLOW) << "Transaction with TTL has non-zero fee: tx = " << id << ", fee = " << m_currency.formatAmount(fee); + tvc.m_verifivation_failed = true; + return false; + } + } + //check key images for transaction if it is not kept by block if (!keptByBlock) { std::lock_guard lock(m_transactions_lock); @@ -192,10 +221,13 @@ namespace CryptoNote { m_paymentIdIndex.add(txd.tx); m_timestampIndex.add(txd.receiveTime, txd.id); + if (ttl.ttl != 0) { + m_ttlIndex.emplace(std::make_pair(id, ttl.ttl)); + } } tvc.m_added_to_pool = true; - tvc.m_should_be_relayed = inputsValid && (fee > 0 || isFusionTransaction); + tvc.m_should_be_relayed = inputsValid && (fee > 0 || isFusionTransaction || ttl.ttl != 0); tvc.m_verifivation_failed = true; if (!addTransactionInputs(id, tx, keptByBlock)) @@ -207,11 +239,11 @@ namespace CryptoNote { } //--------------------------------------------------------------------------------- - bool tx_memory_pool::add_tx(const Transaction &tx, tx_verification_context& tvc, bool keeped_by_block) { + bool tx_memory_pool::add_tx(const Transaction &tx, tx_verification_context& tvc, bool keeped_by_block, uint32_t height) { Crypto::Hash h = NULL_HASH; size_t blobSize = 0; getObjectHash(tx, h, blobSize); - return add_tx(tx, h, blobSize, tvc, keeped_by_block); + return add_tx(tx, h, blobSize, tvc, keeped_by_block, height); } //--------------------------------------------------------------------------------- bool tx_memory_pool::take_tx(const Crypto::Hash &id, Transaction &tx, size_t& blobSize, uint64_t& fee) { @@ -328,7 +360,15 @@ namespace CryptoNote { << "max_used_block_id: " << txd.maxUsedBlock.id << std::endl << "last_failed_height: " << txd.lastFailedBlock.height << std::endl << "last_failed_id: " << txd.lastFailedBlock.id << std::endl - << "received: " << std::ctime(&txd.receiveTime) << std::endl; + << "received: " << std::ctime(&txd.receiveTime); + + auto ttlIt = m_ttlIndex.find(txd.id); + if (ttlIt != m_ttlIndex.end()) { + // ctime() returns string that ends with new line + ss << "TTL: " << std::ctime(reinterpret_cast(&ttlIt->second)); + } + + ss << std::endl; } return ss.str(); @@ -349,6 +389,10 @@ namespace CryptoNote { for (auto it = m_fee_index.rbegin(); it != m_fee_index.rend() && it->fee == 0; ++it) { const auto& txd = *it; + if (m_ttlIndex.count(txd.id) > 0) { + continue; + } + if (m_currency.fusionTxMaxSize() < total_size + txd.blobSize) { continue; } @@ -362,6 +406,10 @@ namespace CryptoNote { for (auto i = m_fee_index.begin(); i != m_fee_index.end(); ++i) { const auto& txd = *i; + if (m_ttlIndex.count(txd.id) > 0) { + continue; + } + size_t blockSizeLimit = (txd.fee == 0) ? median_size : max_total_size; if (blockSizeLimit < total_size + txd.blobSize) { continue; @@ -404,6 +452,7 @@ namespace CryptoNote { m_paymentIdIndex.clear(); m_timestampIndex.clear(); + m_ttlIndex.clear(); } else { buildIndices(); } @@ -428,6 +477,7 @@ namespace CryptoNote { m_paymentIdIndex.clear(); m_timestampIndex.clear(); + m_ttlIndex.clear(); return true; } @@ -498,8 +548,16 @@ namespace CryptoNote { uint64_t txAge = now - it->receiveTime; bool remove = txAge > (it->keptByBlock ? m_currency.mempoolTxFromAltBlockLiveTime() : m_currency.mempoolTxLiveTime()); - if (remove) { - logger(TRACE) << "Tx " << it->id << " removed from tx pool due to outdated, age: " << txAge; + auto ttlIt = m_ttlIndex.find(it->id); + bool ttlExpired = (ttlIt != m_ttlIndex.end() && ttlIt->second <= now); + + if (remove || ttlExpired) { + if (ttlExpired) { + logger(TRACE) << "Tx " << it->id << " removed from tx pool due to expired TTL, TTL : " << ttlIt->second; + } else { + logger(TRACE) << "Tx " << it->id << " removed from tx pool due to outdated, age: " << txAge; + } + m_recentlyDeletedTransactions.emplace(it->id, now); it = removeTransaction(it); somethingRemoved = true; @@ -520,6 +578,7 @@ namespace CryptoNote { removeTransactionInputs(i->id, i->tx, i->keptByBlock); m_paymentIdIndex.remove(i->tx); m_timestampIndex.remove(i->receiveTime, i->id); + m_ttlIndex.erase(i->id); return m_transactions.erase(i); } @@ -618,6 +677,15 @@ namespace CryptoNote { for (auto it = m_transactions.begin(); it != m_transactions.end(); it++) { m_paymentIdIndex.add(it->tx); m_timestampIndex.add(it->receiveTime, it->id); + + std::vector txExtraFields; + parseTransactionExtra(it->tx.extra, txExtraFields); + TransactionExtraTTL ttl; + if (findTransactionExtraFieldByType(txExtraFields, ttl)) { + if (ttl.ttl != 0) { + m_ttlIndex.emplace(std::make_pair(it->id, ttl.ttl)); + } + } } } diff --git a/src/CryptoNoteCore/TransactionPool.h b/src/CryptoNoteCore/TransactionPool.h index bfb7f99..bce26cd 100644 --- a/src/CryptoNoteCore/TransactionPool.h +++ b/src/CryptoNoteCore/TransactionPool.h @@ -75,7 +75,7 @@ namespace CryptoNote { const CryptoNote::Currency& currency, CryptoNote::ITransactionValidator& validator, CryptoNote::ITimeProvider& timeProvider, - Logging::ILogger& log); + Logging::ILogger& log); bool addObserver(ITxPoolObserver* observer); bool removeObserver(ITxPoolObserver* observer); @@ -85,8 +85,8 @@ namespace CryptoNote { bool deinit(); bool have_tx(const Crypto::Hash &id) const; - bool add_tx(const Transaction &tx, const Crypto::Hash &id, size_t blobSize, tx_verification_context& tvc, bool keeped_by_block); - bool add_tx(const Transaction &tx, tx_verification_context& tvc, bool keeped_by_block); + bool add_tx(const Transaction &tx, const Crypto::Hash &id, size_t blobSize, tx_verification_context& tvc, bool keeped_by_block, uint32_t height); + bool add_tx(const Transaction &tx, tx_verification_context& tvc, bool keeped_by_block, uint32_t height); //gets tx and remove it from pool bool take_tx(const Crypto::Hash &id, Transaction &tx, size_t& blobSize, uint64_t& fee); @@ -203,6 +203,7 @@ namespace CryptoNote { PaymentIdIndex m_paymentIdIndex; TimestampTransactionsIndex m_timestampIndex; + std::unordered_map m_ttlIndex; }; } diff --git a/src/CryptoNoteCore/UpgradeDetector.h b/src/CryptoNoteCore/UpgradeDetector.h index 46c840a..e42d977 100644 --- a/src/CryptoNoteCore/UpgradeDetector.h +++ b/src/CryptoNoteCore/UpgradeDetector.h @@ -1,5 +1,5 @@ // Copyright (c) 2011-2016 The Cryptonote developers -// Copyright (c) 2014-2016 SDN developers +// Copyright (c) 2014-2016 XDN-project developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -9,6 +9,9 @@ #include #include +#include "Common/StringTools.h" +#include "CryptoNoteCore/CryptoNoteBasicImpl.h" +#include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/Currency.h" #include "CryptoNoteConfig.h" #include @@ -16,12 +19,12 @@ namespace CryptoNote { class UpgradeDetectorBase { public: - enum : uint64_t { - UNDEF_HEIGHT = static_cast(-1), + enum : uint32_t { + UNDEF_HEIGHT = static_cast(-1), }; }; - static_assert(CryptoNote::UpgradeDetectorBase::UNDEF_HEIGHT == UINT64_C(0xFFFFFFFFFFFFFFFF), "UpgradeDetectorBase::UNDEF_HEIGHT has invalid value"); + static_assert(CryptoNote::UpgradeDetectorBase::UNDEF_HEIGHT == UINT32_C(0xFFFFFFFF), "UpgradeDetectorBase::UNDEF_HEIGHT has invalid value"); template class BasicUpgradeDetector : public UpgradeDetectorBase { @@ -31,10 +34,12 @@ namespace CryptoNote { m_blockchain(blockchain), m_targetVersion(targetVersion), m_votingCompleteHeight(UNDEF_HEIGHT), - logger(log, "upgrade") { } + logger(log, "upgrade") { + } bool init() { - if (m_currency.upgradeHeight() == UNDEF_HEIGHT) { + uint32_t upgradeHeight = m_currency.upgradeHeight(m_targetVersion); + if (upgradeHeight == UNDEF_HEIGHT) { if (m_blockchain.empty()) { m_votingCompleteHeight = UNDEF_HEIGHT; @@ -44,51 +49,73 @@ namespace CryptoNote { } else if (m_targetVersion <= m_blockchain.back().bl.majorVersion) { auto it = std::lower_bound(m_blockchain.begin(), m_blockchain.end(), m_targetVersion, [](const typename BC::value_type& b, uint8_t v) { return b.bl.majorVersion < v; }); - if (!(it != m_blockchain.end() && it->bl.majorVersion == m_targetVersion)) { logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: upgrade height isn't found"; return false; } - uint64_t upgradeHeight = it - m_blockchain.begin(); - m_votingCompleteHeight = findVotingCompleteHeight(upgradeHeight); - if (!(m_votingCompleteHeight != UNDEF_HEIGHT)) { logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: voting complete height isn't found, upgrade height = " << upgradeHeight; return false; } + if (it == m_blockchain.end() || it->bl.majorVersion != m_targetVersion) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: upgrade height isn't found"; + return false; + } + uint32_t upgradeHeight = it - m_blockchain.begin(); + m_votingCompleteHeight = findVotingCompleteHeight(upgradeHeight); + if (m_votingCompleteHeight == UNDEF_HEIGHT) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: voting complete height isn't found, upgrade height = " << upgradeHeight; + return false; + } } else { m_votingCompleteHeight = UNDEF_HEIGHT; } } else if (!m_blockchain.empty()) { - if (m_blockchain.size() <= m_currency.upgradeHeight() + 1) { - if (!(m_blockchain.back().bl.majorVersion == m_targetVersion - 1)) { logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: block at height " << (m_blockchain.size() - 1) << " has invalid version " << - static_cast(m_blockchain.back().bl.majorVersion) << ", expected " << static_cast(m_targetVersion); return false; } + if (m_blockchain.size() <= upgradeHeight + 1) { + if (m_blockchain.back().bl.majorVersion >= m_targetVersion) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: block at height " << (m_blockchain.size() - 1) << + " has invalid version " << static_cast(m_blockchain.back().bl.majorVersion) << + ", expected " << static_cast(m_targetVersion - 1) << " or less"; + return false; + } } else { - int blockVersionAtUpgradeHeight = m_blockchain[m_currency.upgradeHeight()].bl.majorVersion; - if (!(blockVersionAtUpgradeHeight == m_targetVersion - 1)) { logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: block at height " << m_currency.upgradeHeight() << " has invalid version " << - blockVersionAtUpgradeHeight << ", expected " << static_cast(m_targetVersion - 1); return false; } + int blockVersionAtUpgradeHeight = m_blockchain[upgradeHeight].bl.majorVersion; + if (blockVersionAtUpgradeHeight != m_targetVersion - 1) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: block at height " << upgradeHeight << + " has invalid version " << blockVersionAtUpgradeHeight << + ", expected " << static_cast(m_targetVersion - 1); + return false; + } - int blockVersionAfterUpgradeHeight = m_blockchain[m_currency.upgradeHeight() + 1].bl.majorVersion; - if (!(blockVersionAfterUpgradeHeight == m_targetVersion)) { logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: block at height " << (m_currency.upgradeHeight() + 1) << " has invalid version " << - blockVersionAfterUpgradeHeight << ", expected " << static_cast(m_targetVersion); return false; } + int blockVersionAfterUpgradeHeight = m_blockchain[upgradeHeight + 1].bl.majorVersion; + if (blockVersionAfterUpgradeHeight != m_targetVersion) { + logger(Logging::ERROR, Logging::BRIGHT_RED) << "Internal error: block at height " << (upgradeHeight + 1) << + " has invalid version " << blockVersionAfterUpgradeHeight << + ", expected " << static_cast(m_targetVersion); + return false; + } } } return true; } - uint8_t targetVersion() const { return m_targetVersion; } - uint64_t votingCompleteHeight() const { return m_votingCompleteHeight; } + uint8_t targetVersion() const { + return m_targetVersion; + } + uint32_t votingCompleteHeight() const { + return m_votingCompleteHeight; + } - uint64_t upgradeHeight() const { - if (m_currency.upgradeHeight() == UNDEF_HEIGHT) { + uint32_t upgradeHeight() const { + if (m_currency.upgradeHeight(m_targetVersion) == UNDEF_HEIGHT) { return m_votingCompleteHeight == UNDEF_HEIGHT ? UNDEF_HEIGHT : m_currency.calculateUpgradeHeight(m_votingCompleteHeight); } else { - return m_currency.upgradeHeight(); + return m_currency.upgradeHeight(m_targetVersion); } } void blockPushed() { assert(!m_blockchain.empty()); - if (m_currency.upgradeHeight() != UNDEF_HEIGHT) { - if (m_blockchain.size() <= m_currency.upgradeHeight() + 1) { - assert(m_blockchain.back().bl.majorVersion == m_targetVersion - 1); + if (m_currency.upgradeHeight(m_targetVersion) != UNDEF_HEIGHT) { + if (m_blockchain.size() <= m_currency.upgradeHeight(m_targetVersion) + 1) { + assert(m_blockchain.back().bl.majorVersion <= m_targetVersion - 1); } else { - assert(m_blockchain.back().bl.majorVersion == m_targetVersion); + assert(m_blockchain.back().bl.majorVersion >= m_targetVersion); } } else if (m_votingCompleteHeight != UNDEF_HEIGHT) { @@ -98,33 +125,41 @@ namespace CryptoNote { assert(m_blockchain.back().bl.majorVersion == m_targetVersion - 1); if (m_blockchain.size() % (60 * 60 / m_currency.difficultyTarget()) == 0) { - logger(Logging::TRACE, Logging::BRIGHT_GREEN) << "###### UPGRADE is going to happen after height " << upgradeHeight() << "!"; + auto interval = m_currency.difficultyTarget() * (upgradeHeight() - m_blockchain.size() + 2); + time_t upgradeTimestamp = time(nullptr) + static_cast(interval); + struct tm* upgradeTime = localtime(&upgradeTimestamp);; + char upgradeTimeStr[40]; + strftime(upgradeTimeStr, 40, "%H:%M:%S %Y.%m.%d", upgradeTime); + + logger(Logging::TRACE, Logging::BRIGHT_GREEN) << "###### UPGRADE is going to happen after block index " << upgradeHeight() << " at about " << + upgradeTimeStr << " (in " << Common::timeIntervalToString(interval) << ")! Current last block index " << (m_blockchain.size() - 1) << + ", hash " << get_block_hash(m_blockchain.back().bl); } } else if (m_blockchain.size() == upgradeHeight() + 1) { assert(m_blockchain.back().bl.majorVersion == m_targetVersion - 1); - logger(Logging::TRACE, Logging::BRIGHT_GREEN) << "###### UPGRADE has happened! Starting from height " << (upgradeHeight() + 1) << + logger(Logging::TRACE, Logging::BRIGHT_GREEN) << "###### UPGRADE has happened! Starting from block index " << (upgradeHeight() + 1) << " blocks with major version below " << static_cast(m_targetVersion) << " will be rejected!"; } else { assert(m_blockchain.back().bl.majorVersion == m_targetVersion); } } else { - uint64_t lastBlockHeight = m_blockchain.size() - 1; + uint32_t lastBlockHeight = m_blockchain.size() - 1; if (isVotingComplete(lastBlockHeight)) { m_votingCompleteHeight = lastBlockHeight; - logger(Logging::TRACE, Logging::BRIGHT_GREEN) << "###### UPGRADE voting complete at height " << m_votingCompleteHeight << - "! UPGRADE is going to happen after height " << upgradeHeight() << "!"; + logger(Logging::TRACE, Logging::BRIGHT_GREEN) << "###### UPGRADE voting complete at block index " << m_votingCompleteHeight << + "! UPGRADE is going to happen after block index " << upgradeHeight() << "!"; } } } void blockPopped() { if (m_votingCompleteHeight != UNDEF_HEIGHT) { - assert(m_currency.upgradeHeight() == UNDEF_HEIGHT); + assert(m_currency.upgradeHeight(m_targetVersion) == UNDEF_HEIGHT); if (m_blockchain.size() == m_votingCompleteHeight) { - logger(Logging::TRACE, Logging::BRIGHT_YELLOW) << "###### UPGRADE after height " << upgradeHeight() << " has been cancelled!"; + logger(Logging::TRACE, Logging::BRIGHT_YELLOW) << "###### UPGRADE after block index " << upgradeHeight() << " has been canceled!"; m_votingCompleteHeight = UNDEF_HEIGHT; } else { assert(m_blockchain.size() > m_votingCompleteHeight); @@ -132,12 +167,25 @@ namespace CryptoNote { } } + size_t getNumberOfVotes(uint32_t height) { + if (height < m_currency.upgradeVotingWindow() - 1) { + return 0; + } + + size_t voteCounter = 0; + for (size_t i = height + 1 - m_currency.upgradeVotingWindow(); i <= height; ++i) { + const auto& b = m_blockchain[i].bl; + voteCounter += (b.majorVersion == m_targetVersion - 1) && (b.minorVersion == BLOCK_MINOR_VERSION_1) ? 1 : 0; + } + + return voteCounter; + } + private: - uint64_t findVotingCompleteHeight(uint64_t probableUpgradeHeight) { - assert(m_currency.upgradeHeight() == UNDEF_HEIGHT); + uint32_t findVotingCompleteHeight(uint32_t probableUpgradeHeight) { + assert(m_currency.upgradeHeight(m_targetVersion) == UNDEF_HEIGHT); - uint64_t probableVotingCompleteHeight = probableUpgradeHeight > m_currency.maxUpgradeDistance() ? - probableUpgradeHeight - m_currency.maxUpgradeDistance() : 0; + uint32_t probableVotingCompleteHeight = probableUpgradeHeight > m_currency.maxUpgradeDistance() ? probableUpgradeHeight - m_currency.maxUpgradeDistance() : 0; for (size_t i = probableVotingCompleteHeight; i <= probableUpgradeHeight; ++i) { if (isVotingComplete(i)) { return i; @@ -147,21 +195,12 @@ namespace CryptoNote { return UNDEF_HEIGHT; } - bool isVotingComplete(uint64_t height) { - assert(m_currency.upgradeHeight() == UNDEF_HEIGHT); + bool isVotingComplete(uint32_t height) { + assert(m_currency.upgradeHeight(m_targetVersion) == UNDEF_HEIGHT); assert(m_currency.upgradeVotingWindow() > 1); assert(m_currency.upgradeVotingThreshold() > 0 && m_currency.upgradeVotingThreshold() <= 100); - if (height < static_cast(m_currency.upgradeVotingWindow()) - 1) { - return false; - } - - unsigned int voteCounter = 0; - for (size_t i = height + 1 - m_currency.upgradeVotingWindow(); i <= height; ++i) { - const auto& b = m_blockchain[i].bl; - voteCounter += (b.majorVersion == m_targetVersion - 1) && (b.minorVersion == BLOCK_MINOR_VERSION_1) ? 1 : 0; - } - + size_t voteCounter = getNumberOfVotes(height); return m_currency.upgradeVotingThreshold() * m_currency.upgradeVotingWindow() <= 100 * voteCounter; } @@ -170,6 +209,6 @@ namespace CryptoNote { const Currency& m_currency; BC& m_blockchain; uint8_t m_targetVersion; - uint64_t m_votingCompleteHeight; + uint32_t m_votingCompleteHeight; }; } diff --git a/src/Mnemonics/chinese_simplified.h b/src/Mnemonics/chinese_simplified.h new file mode 100644 index 0000000..7d9cf8d --- /dev/null +++ b/src/Mnemonics/chinese_simplified.h @@ -0,0 +1,1709 @@ +// Word list originally created by dabura667 and released under The MIT License (MIT) +// +// The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Code surrounding the word list is Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file chinese_simplified.h + * + * \brief Simplified Chinese word list and map. + */ + +#ifndef CHINESE_SIMPLIFIED_H +#define CHINESE_SIMPLIFIED_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Chinese_Simplified: public Base + { + public: + Chinese_Simplified(): Base("简体中文 (中国)", std::vector({ + "的", + "一", + "是", + "在", + "不", + "了", + "有", + "和", + "人", + "这", + "中", + "大", + "为", + "上", + "个", + "国", + "我", + "以", + "要", + "他", + "时", + "来", + "用", + "们", + "生", + "到", + "作", + "地", + "于", + "出", + "就", + "分", + "对", + "成", + "会", + "可", + "主", + "发", + "年", + "动", + "同", + "工", + "也", + "能", + "下", + "过", + "子", + "说", + "产", + "种", + "面", + "而", + "方", + "后", + "多", + "定", + "行", + "学", + "法", + "所", + "民", + "得", + "经", + "十", + "三", + "之", + "进", + "着", + "等", + "部", + "度", + "家", + "电", + "力", + "里", + "如", + "水", + "化", + "高", + "自", + "二", + "理", + "起", + "小", + "物", + "现", + "实", + "加", + "量", + "都", + "两", + "体", + "制", + "机", + "当", + "使", + "点", + "从", + "业", + "本", + "去", + "把", + "性", + "好", + "应", + "开", + "它", + "合", + "还", + "因", + "由", + "其", + "些", + "然", + "前", + "外", + "天", + "政", + "四", + "日", + "那", + "社", + "义", + "事", + "平", + "形", + "相", + "全", + "表", + "间", + "样", + "与", + "关", + "各", + "重", + "新", + "线", + "内", + "数", + "正", + "心", + "反", + "你", + "明", + "看", + "原", + "又", + "么", + "利", + "比", + "或", + "但", + "质", + "气", + "第", + "向", + "道", + "命", + "此", + "变", + "条", + "只", + "没", + "结", + "解", + "问", + "意", + "建", + "月", + "公", + "无", + "系", + "军", + "很", + "情", + "者", + "最", + "立", + "代", + "想", + "已", + "通", + "并", + "提", + "直", + "题", + "党", + "程", + "展", + "五", + "果", + "料", + "象", + "员", + "革", + "位", + "入", + "常", + "文", + "总", + "次", + "品", + "式", + "活", + "设", + "及", + "管", + "特", + "件", + "长", + "求", + "老", + "头", + "基", + "资", + "边", + "流", + "路", + "级", + "少", + "图", + "山", + "统", + "接", + "知", + "较", + "将", + "组", + "见", + "计", + "别", + "她", + "手", + "角", + "期", + "根", + "论", + "运", + "农", + "指", + "几", + "九", + "区", + "强", + "放", + "决", + "西", + "被", + "干", + "做", + "必", + "战", + "先", + "回", + "则", + "任", + "取", + "据", + "处", + "队", + "南", + "给", + "色", + "光", + "门", + "即", + "保", + "治", + "北", + "造", + "百", + "规", + "热", + "领", + "七", + "海", + "口", + "东", + "导", + "器", + "压", + "志", + "世", + "金", + "增", + "争", + "济", + "阶", + "油", + "思", + "术", + "极", + "交", + "受", + "联", + "什", + "认", + "六", + "共", + "权", + "收", + "证", + "改", + "清", + "美", + "再", + "采", + "转", + "更", + "单", + "风", + "切", + "打", + "白", + "教", + "速", + "花", + "带", + "安", + "场", + "身", + "车", + "例", + "真", + "务", + "具", + "万", + "每", + "目", + "至", + "达", + "走", + "积", + "示", + "议", + "声", + "报", + "斗", + "完", + "类", + "八", + "离", + "华", + "名", + "确", + "才", + "科", + "张", + "信", + "马", + "节", + "话", + "米", + "整", + "空", + "元", + "况", + "今", + "集", + "温", + "传", + "土", + "许", + "步", + "群", + "广", + "石", + "记", + "需", + "段", + "研", + "界", + "拉", + "林", + "律", + "叫", + "且", + "究", + "观", + "越", + "织", + "装", + "影", + "算", + "低", + "持", + "音", + "众", + "书", + "布", + "复", + "容", + "儿", + "须", + "际", + "商", + "非", + "验", + "连", + "断", + "深", + "难", + "近", + "矿", + "千", + "周", + "委", + "素", + "技", + "备", + "半", + "办", + "青", + "省", + "列", + "习", + "响", + "约", + "支", + "般", + "史", + "感", + "劳", + "便", + "团", + "往", + "酸", + "历", + "市", + "克", + "何", + "除", + "消", + "构", + "府", + "称", + "太", + "准", + "精", + "值", + "号", + "率", + "族", + "维", + "划", + "选", + "标", + "写", + "存", + "候", + "毛", + "亲", + "快", + "效", + "斯", + "院", + "查", + "江", + "型", + "眼", + "王", + "按", + "格", + "养", + "易", + "置", + "派", + "层", + "片", + "始", + "却", + "专", + "状", + "育", + "厂", + "京", + "识", + "适", + "属", + "圆", + "包", + "火", + "住", + "调", + "满", + "县", + "局", + "照", + "参", + "红", + "细", + "引", + "听", + "该", + "铁", + "价", + "严", + "首", + "底", + "液", + "官", + "德", + "随", + "病", + "苏", + "失", + "尔", + "死", + "讲", + "配", + "女", + "黄", + "推", + "显", + "谈", + "罪", + "神", + "艺", + "呢", + "席", + "含", + "企", + "望", + "密", + "批", + "营", + "项", + "防", + "举", + "球", + "英", + "氧", + "势", + "告", + "李", + "台", + "落", + "木", + "帮", + "轮", + "破", + "亚", + "师", + "围", + "注", + "远", + "字", + "材", + "排", + "供", + "河", + "态", + "封", + "另", + "施", + "减", + "树", + "溶", + "怎", + "止", + "案", + "言", + "士", + "均", + "武", + "固", + "叶", + "鱼", + "波", + "视", + "仅", + "费", + "紧", + "爱", + "左", + "章", + "早", + "朝", + "害", + "续", + "轻", + "服", + "试", + "食", + "充", + "兵", + "源", + "判", + "护", + "司", + "足", + "某", + "练", + "差", + "致", + "板", + "田", + "降", + "黑", + "犯", + "负", + "击", + "范", + "继", + "兴", + "似", + "余", + "坚", + "曲", + "输", + "修", + "故", + "城", + "夫", + "够", + "送", + "笔", + "船", + "占", + "右", + "财", + "吃", + "富", + "春", + "职", + "觉", + "汉", + "画", + "功", + "巴", + "跟", + "虽", + "杂", + "飞", + "检", + "吸", + "助", + "升", + "阳", + "互", + "初", + "创", + "抗", + "考", + "投", + "坏", + "策", + "古", + "径", + "换", + "未", + "跑", + "留", + "钢", + "曾", + "端", + "责", + "站", + "简", + "述", + "钱", + "副", + "尽", + "帝", + "射", + "草", + "冲", + "承", + "独", + "令", + "限", + "阿", + "宣", + "环", + "双", + "请", + "超", + "微", + "让", + "控", + "州", + "良", + "轴", + "找", + "否", + "纪", + "益", + "依", + "优", + "顶", + "础", + "载", + "倒", + "房", + "突", + "坐", + "粉", + "敌", + "略", + "客", + "袁", + "冷", + "胜", + "绝", + "析", + "块", + "剂", + "测", + "丝", + "协", + "诉", + "念", + "陈", + "仍", + "罗", + "盐", + "友", + "洋", + "错", + "苦", + "夜", + "刑", + "移", + "频", + "逐", + "靠", + "混", + "母", + "短", + "皮", + "终", + "聚", + "汽", + "村", + "云", + "哪", + "既", + "距", + "卫", + "停", + "烈", + "央", + "察", + "烧", + "迅", + "境", + "若", + "印", + "洲", + "刻", + "括", + "激", + "孔", + "搞", + "甚", + "室", + "待", + "核", + "校", + "散", + "侵", + "吧", + "甲", + "游", + "久", + "菜", + "味", + "旧", + "模", + "湖", + "货", + "损", + "预", + "阻", + "毫", + "普", + "稳", + "乙", + "妈", + "植", + "息", + "扩", + "银", + "语", + "挥", + "酒", + "守", + "拿", + "序", + "纸", + "医", + "缺", + "雨", + "吗", + "针", + "刘", + "啊", + "急", + "唱", + "误", + "训", + "愿", + "审", + "附", + "获", + "茶", + "鲜", + "粮", + "斤", + "孩", + "脱", + "硫", + "肥", + "善", + "龙", + "演", + "父", + "渐", + "血", + "欢", + "械", + "掌", + "歌", + "沙", + "刚", + "攻", + "谓", + "盾", + "讨", + "晚", + "粒", + "乱", + "燃", + "矛", + "乎", + "杀", + "药", + "宁", + "鲁", + "贵", + "钟", + "煤", + "读", + "班", + "伯", + "香", + "介", + "迫", + "句", + "丰", + "培", + "握", + "兰", + "担", + "弦", + "蛋", + "沉", + "假", + "穿", + "执", + "答", + "乐", + "谁", + "顺", + "烟", + "缩", + "征", + "脸", + "喜", + "松", + "脚", + "困", + "异", + "免", + "背", + "星", + "福", + "买", + "染", + "井", + "概", + "慢", + "怕", + "磁", + "倍", + "祖", + "皇", + "促", + "静", + "补", + "评", + "翻", + "肉", + "践", + "尼", + "衣", + "宽", + "扬", + "棉", + "希", + "伤", + "操", + "垂", + "秋", + "宜", + "氢", + "套", + "督", + "振", + "架", + "亮", + "末", + "宪", + "庆", + "编", + "牛", + "触", + "映", + "雷", + "销", + "诗", + "座", + "居", + "抓", + "裂", + "胞", + "呼", + "娘", + "景", + "威", + "绿", + "晶", + "厚", + "盟", + "衡", + "鸡", + "孙", + "延", + "危", + "胶", + "屋", + "乡", + "临", + "陆", + "顾", + "掉", + "呀", + "灯", + "岁", + "措", + "束", + "耐", + "剧", + "玉", + "赵", + "跳", + "哥", + "季", + "课", + "凯", + "胡", + "额", + "款", + "绍", + "卷", + "齐", + "伟", + "蒸", + "殖", + "永", + "宗", + "苗", + "川", + "炉", + "岩", + "弱", + "零", + "杨", + "奏", + "沿", + "露", + "杆", + "探", + "滑", + "镇", + "饭", + "浓", + "航", + "怀", + "赶", + "库", + "夺", + "伊", + "灵", + "税", + "途", + "灭", + "赛", + "归", + "召", + "鼓", + "播", + "盘", + "裁", + "险", + "康", + "唯", + "录", + "菌", + "纯", + "借", + "糖", + "盖", + "横", + "符", + "私", + "努", + "堂", + "域", + "枪", + "润", + "幅", + "哈", + "竟", + "熟", + "虫", + "泽", + "脑", + "壤", + "碳", + "欧", + "遍", + "侧", + "寨", + "敢", + "彻", + "虑", + "斜", + "薄", + "庭", + "纳", + "弹", + "饲", + "伸", + "折", + "麦", + "湿", + "暗", + "荷", + "瓦", + "塞", + "床", + "筑", + "恶", + "户", + "访", + "塔", + "奇", + "透", + "梁", + "刀", + "旋", + "迹", + "卡", + "氯", + "遇", + "份", + "毒", + "泥", + "退", + "洗", + "摆", + "灰", + "彩", + "卖", + "耗", + "夏", + "择", + "忙", + "铜", + "献", + "硬", + "予", + "繁", + "圈", + "雪", + "函", + "亦", + "抽", + "篇", + "阵", + "阴", + "丁", + "尺", + "追", + "堆", + "雄", + "迎", + "泛", + "爸", + "楼", + "避", + "谋", + "吨", + "野", + "猪", + "旗", + "累", + "偏", + "典", + "馆", + "索", + "秦", + "脂", + "潮", + "爷", + "豆", + "忽", + "托", + "惊", + "塑", + "遗", + "愈", + "朱", + "替", + "纤", + "粗", + "倾", + "尚", + "痛", + "楚", + "谢", + "奋", + "购", + "磨", + "君", + "池", + "旁", + "碎", + "骨", + "监", + "捕", + "弟", + "暴", + "割", + "贯", + "殊", + "释", + "词", + "亡", + "壁", + "顿", + "宝", + "午", + "尘", + "闻", + "揭", + "炮", + "残", + "冬", + "桥", + "妇", + "警", + "综", + "招", + "吴", + "付", + "浮", + "遭", + "徐", + "您", + "摇", + "谷", + "赞", + "箱", + "隔", + "订", + "男", + "吹", + "园", + "纷", + "唐", + "败", + "宋", + "玻", + "巨", + "耕", + "坦", + "荣", + "闭", + "湾", + "键", + "凡", + "驻", + "锅", + "救", + "恩", + "剥", + "凝", + "碱", + "齿", + "截", + "炼", + "麻", + "纺", + "禁", + "废", + "盛", + "版", + "缓", + "净", + "睛", + "昌", + "婚", + "涉", + "筒", + "嘴", + "插", + "岸", + "朗", + "庄", + "街", + "藏", + "姑", + "贸", + "腐", + "奴", + "啦", + "惯", + "乘", + "伙", + "恢", + "匀", + "纱", + "扎", + "辩", + "耳", + "彪", + "臣", + "亿", + "璃", + "抵", + "脉", + "秀", + "萨", + "俄", + "网", + "舞", + "店", + "喷", + "纵", + "寸", + "汗", + "挂", + "洪", + "贺", + "闪", + "柬", + "爆", + "烯", + "津", + "稻", + "墙", + "软", + "勇", + "像", + "滚", + "厘", + "蒙", + "芳", + "肯", + "坡", + "柱", + "荡", + "腿", + "仪", + "旅", + "尾", + "轧", + "冰", + "贡", + "登", + "黎", + "削", + "钻", + "勒", + "逃", + "障", + "氨", + "郭", + "峰", + "币", + "港", + "伏", + "轨", + "亩", + "毕", + "擦", + "莫", + "刺", + "浪", + "秘", + "援", + "株", + "健", + "售", + "股", + "岛", + "甘", + "泡", + "睡", + "童", + "铸", + "汤", + "阀", + "休", + "汇", + "舍", + "牧", + "绕", + "炸", + "哲", + "磷", + "绩", + "朋", + "淡", + "尖", + "启", + "陷", + "柴", + "呈", + "徒", + "颜", + "泪", + "稍", + "忘", + "泵", + "蓝", + "拖", + "洞", + "授", + "镜", + "辛", + "壮", + "锋", + "贫", + "虚", + "弯", + "摩", + "泰", + "幼", + "廷", + "尊", + "窗", + "纲", + "弄", + "隶", + "疑", + "氏", + "宫", + "姐", + "震", + "瑞", + "怪", + "尤", + "琴", + "循", + "描", + "膜", + "违", + "夹", + "腰", + "缘", + "珠", + "穷", + "森", + "枝", + "竹", + "沟", + "催", + "绳", + "忆", + "邦", + "剩", + "幸", + "浆", + "栏", + "拥", + "牙", + "贮", + "礼", + "滤", + "钠", + "纹", + "罢", + "拍", + "咱", + "喊", + "袖", + "埃", + "勤", + "罚", + "焦", + "潜", + "伍", + "墨", + "欲", + "缝", + "姓", + "刊", + "饱", + "仿", + "奖", + "铝", + "鬼", + "丽", + "跨", + "默", + "挖", + "链", + "扫", + "喝", + "袋", + "炭", + "污", + "幕", + "诸", + "弧", + "励", + "梅", + "奶", + "洁", + "灾", + "舟", + "鉴", + "苯", + "讼", + "抱", + "毁", + "懂", + "寒", + "智", + "埔", + "寄", + "届", + "跃", + "渡", + "挑", + "丹", + "艰", + "贝", + "碰", + "拔", + "爹", + "戴", + "码", + "梦", + "芽", + "熔", + "赤", + "渔", + "哭", + "敬", + "颗", + "奔", + "铅", + "仲", + "虎", + "稀", + "妹", + "乏", + "珍", + "申", + "桌", + "遵", + "允", + "隆", + "螺", + "仓", + "魏", + "锐", + "晓", + "氮", + "兼", + "隐", + "碍", + "赫", + "拨", + "忠", + "肃", + "缸", + "牵", + "抢", + "博", + "巧", + "壳", + "兄", + "杜", + "讯", + "诚", + "碧", + "祥", + "柯", + "页", + "巡", + "矩", + "悲", + "灌", + "龄", + "伦", + "票", + "寻", + "桂", + "铺", + "圣", + "恐", + "恰", + "郑", + "趣", + "抬", + "荒", + "腾", + "贴", + "柔", + "滴", + "猛", + "阔", + "辆", + "妻", + "填", + "撤", + "储", + "签", + "闹", + "扰", + "紫", + "砂", + "递", + "戏", + "吊", + "陶", + "伐", + "喂", + "疗", + "瓶", + "婆", + "抚", + "臂", + "摸", + "忍", + "虾", + "蜡", + "邻", + "胸", + "巩", + "挤", + "偶", + "弃", + "槽", + "劲", + "乳", + "邓", + "吉", + "仁", + "烂", + "砖", + "租", + "乌", + "舰", + "伴", + "瓜", + "浅", + "丙", + "暂", + "燥", + "橡", + "柳", + "迷", + "暖", + "牌", + "秧", + "胆", + "详", + "簧", + "踏", + "瓷", + "谱", + "呆", + "宾", + "糊", + "洛", + "辉", + "愤", + "竞", + "隙", + "怒", + "粘", + "乃", + "绪", + "肩", + "籍", + "敏", + "涂", + "熙", + "皆", + "侦", + "悬", + "掘", + "享", + "纠", + "醒", + "狂", + "锁", + "淀", + "恨", + "牲", + "霸", + "爬", + "赏", + "逆", + "玩", + "陵", + "祝", + "秒", + "浙", + "貌" + }), 1) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/dutch.h b/src/Mnemonics/dutch.h new file mode 100644 index 0000000..72f9799 --- /dev/null +++ b/src/Mnemonics/dutch.h @@ -0,0 +1,1686 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file dutch.h + * + * \brief New Dutch word list and map. + */ + +#ifndef DUTCH_H +#define DUTCH_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Dutch: public Base + { + public: + Dutch(): Base("Nederlands", std::vector({ + "aalglad", + "aalscholver", + "aambeeld", + "aangeef", + "aanlandig", + "aanvaard", + "aanwakker", + "aapmens", + "aarten", + "abdicatie", + "abnormaal", + "abrikoos", + "accu", + "acuut", + "adjudant", + "admiraal", + "advies", + "afbidding", + "afdracht", + "affaire", + "affiche", + "afgang", + "afkick", + "afknap", + "aflees", + "afmijner", + "afname", + "afpreekt", + "afrader", + "afspeel", + "aftocht", + "aftrek", + "afzijdig", + "ahornboom", + "aktetas", + "akzo", + "alchemist", + "alcohol", + "aldaar", + "alexander", + "alfabet", + "alfredo", + "alice", + "alikruik", + "allrisk", + "altsax", + "alufolie", + "alziend", + "amai", + "ambacht", + "ambieer", + "amina", + "amnestie", + "amok", + "ampul", + "amuzikaal", + "angela", + "aniek", + "antje", + "antwerpen", + "anya", + "aorta", + "apache", + "apekool", + "appelaar", + "arganolie", + "argeloos", + "armoede", + "arrenslee", + "artritis", + "arubaan", + "asbak", + "ascii", + "asgrauw", + "asjes", + "asml", + "aspunt", + "asurn", + "asveld", + "aterling", + "atomair", + "atrium", + "atsma", + "atypisch", + "auping", + "aura", + "avifauna", + "axiaal", + "azoriaan", + "azteek", + "azuur", + "bachelor", + "badderen", + "badhotel", + "badmantel", + "badsteden", + "balie", + "ballans", + "balvers", + "bamibal", + "banneling", + "barracuda", + "basaal", + "batelaan", + "batje", + "beambte", + "bedlamp", + "bedwelmd", + "befaamd", + "begierd", + "begraaf", + "behield", + "beijaard", + "bejaagd", + "bekaaid", + "beks", + "bektas", + "belaad", + "belboei", + "belderbos", + "beloerd", + "beluchten", + "bemiddeld", + "benadeeld", + "benijd", + "berechten", + "beroemd", + "besef", + "besseling", + "best", + "betichten", + "bevind", + "bevochten", + "bevraagd", + "bewust", + "bidplaats", + "biefstuk", + "biemans", + "biezen", + "bijbaan", + "bijeenkom", + "bijfiguur", + "bijkaart", + "bijlage", + "bijpaard", + "bijtgaar", + "bijweg", + "bimmel", + "binck", + "bint", + "biobak", + "biotisch", + "biseks", + "bistro", + "bitter", + "bitumen", + "bizar", + "blad", + "bleken", + "blender", + "bleu", + "blief", + "blijven", + "blozen", + "bock", + "boef", + "boei", + "boks", + "bolder", + "bolus", + "bolvormig", + "bomaanval", + "bombarde", + "bomma", + "bomtapijt", + "bookmaker", + "boos", + "borg", + "bosbes", + "boshuizen", + "bosloop", + "botanicus", + "bougie", + "bovag", + "boxspring", + "braad", + "brasem", + "brevet", + "brigade", + "brinckman", + "bruid", + "budget", + "buffel", + "buks", + "bulgaar", + "buma", + "butaan", + "butler", + "buuf", + "cactus", + "cafeetje", + "camcorder", + "cannabis", + "canyon", + "capoeira", + "capsule", + "carkit", + "casanova", + "catalaan", + "ceintuur", + "celdeling", + "celplasma", + "cement", + "censeren", + "ceramisch", + "cerberus", + "cerebraal", + "cesium", + "cirkel", + "citeer", + "civiel", + "claxon", + "clenbuterol", + "clicheren", + "clijsen", + "coalitie", + "coassistentschap", + "coaxiaal", + "codetaal", + "cofinanciering", + "cognac", + "coltrui", + "comfort", + "commandant", + "condensaat", + "confectie", + "conifeer", + "convector", + "copier", + "corfu", + "correct", + "coup", + "couvert", + "creatie", + "credit", + "crematie", + "cricket", + "croupier", + "cruciaal", + "cruijff", + "cuisine", + "culemborg", + "culinair", + "curve", + "cyrano", + "dactylus", + "dading", + "dagblind", + "dagje", + "daglicht", + "dagprijs", + "dagranden", + "dakdekker", + "dakpark", + "dakterras", + "dalgrond", + "dambord", + "damkat", + "damlengte", + "damman", + "danenberg", + "debbie", + "decibel", + "defect", + "deformeer", + "degelijk", + "degradant", + "dejonghe", + "dekken", + "deppen", + "derek", + "derf", + "derhalve", + "detineren", + "devalueer", + "diaken", + "dicht", + "dictaat", + "dief", + "digitaal", + "dijbreuk", + "dijkmans", + "dimbaar", + "dinsdag", + "diode", + "dirigeer", + "disbalans", + "dobermann", + "doenbaar", + "doerak", + "dogma", + "dokhaven", + "dokwerker", + "doling", + "dolphijn", + "dolven", + "dombo", + "dooraderd", + "dopeling", + "doping", + "draderig", + "drama", + "drenkbak", + "dreumes", + "drol", + "drug", + "duaal", + "dublin", + "duplicaat", + "durven", + "dusdanig", + "dutchbat", + "dutje", + "dutten", + "duur", + "duwwerk", + "dwaal", + "dweil", + "dwing", + "dyslexie", + "ecostroom", + "ecotaks", + "educatie", + "eeckhout", + "eede", + "eemland", + "eencellig", + "eeneiig", + "eenruiter", + "eenwinter", + "eerenberg", + "eerrover", + "eersel", + "eetmaal", + "efteling", + "egaal", + "egtberts", + "eickhoff", + "eidooier", + "eiland", + "eind", + "eisden", + "ekster", + "elburg", + "elevatie", + "elfkoppig", + "elfrink", + "elftal", + "elimineer", + "elleboog", + "elma", + "elodie", + "elsa", + "embleem", + "embolie", + "emoe", + "emonds", + "emplooi", + "enduro", + "enfin", + "engageer", + "entourage", + "entstof", + "epileer", + "episch", + "eppo", + "erasmus", + "erboven", + "erebaan", + "erelijst", + "ereronden", + "ereteken", + "erfhuis", + "erfwet", + "erger", + "erica", + "ermitage", + "erna", + "ernie", + "erts", + "ertussen", + "eruitzien", + "ervaar", + "erven", + "erwt", + "esbeek", + "escort", + "esdoorn", + "essing", + "etage", + "eter", + "ethanol", + "ethicus", + "etholoog", + "eufonisch", + "eurocent", + "evacuatie", + "exact", + "examen", + "executant", + "exen", + "exit", + "exogeen", + "exotherm", + "expeditie", + "expletief", + "expres", + "extase", + "extinctie", + "faal", + "faam", + "fabel", + "facultair", + "fakir", + "fakkel", + "faliekant", + "fallisch", + "famke", + "fanclub", + "fase", + "fatsoen", + "fauna", + "federaal", + "feedback", + "feest", + "feilbaar", + "feitelijk", + "felblauw", + "figurante", + "fiod", + "fitheid", + "fixeer", + "flap", + "fleece", + "fleur", + "flexibel", + "flits", + "flos", + "flow", + "fluweel", + "foezelen", + "fokkelman", + "fokpaard", + "fokvee", + "folder", + "follikel", + "folmer", + "folteraar", + "fooi", + "foolen", + "forfait", + "forint", + "formule", + "fornuis", + "fosfaat", + "foxtrot", + "foyer", + "fragiel", + "frater", + "freak", + "freddie", + "fregat", + "freon", + "frijnen", + "fructose", + "frunniken", + "fuiven", + "funshop", + "furieus", + "fysica", + "gadget", + "galder", + "galei", + "galg", + "galvlieg", + "galzuur", + "ganesh", + "gaswet", + "gaza", + "gazelle", + "geaaid", + "gebiecht", + "gebufferd", + "gedijd", + "geef", + "geflanst", + "gefreesd", + "gegaan", + "gegijzeld", + "gegniffel", + "gegraaid", + "gehikt", + "gehobbeld", + "gehucht", + "geiser", + "geiten", + "gekaakt", + "gekheid", + "gekijf", + "gekmakend", + "gekocht", + "gekskap", + "gekte", + "gelubberd", + "gemiddeld", + "geordend", + "gepoederd", + "gepuft", + "gerda", + "gerijpt", + "geseald", + "geshockt", + "gesierd", + "geslaagd", + "gesnaaid", + "getracht", + "getwijfel", + "geuit", + "gevecht", + "gevlagd", + "gewicht", + "gezaagd", + "gezocht", + "ghanees", + "giebelen", + "giechel", + "giepmans", + "gips", + "giraal", + "gistachtig", + "gitaar", + "glaasje", + "gletsjer", + "gleuf", + "glibberen", + "glijbaan", + "gloren", + "gluipen", + "gluren", + "gluur", + "gnoe", + "goddelijk", + "godgans", + "godschalk", + "godzalig", + "goeierd", + "gogme", + "goklustig", + "gokwereld", + "gonggrijp", + "gonje", + "goor", + "grabbel", + "graf", + "graveer", + "grif", + "grolleman", + "grom", + "groosman", + "grubben", + "gruijs", + "grut", + "guacamole", + "guido", + "guppy", + "haazen", + "hachelijk", + "haex", + "haiku", + "hakhout", + "hakken", + "hanegem", + "hans", + "hanteer", + "harrie", + "hazebroek", + "hedonist", + "heil", + "heineken", + "hekhuis", + "hekman", + "helbig", + "helga", + "helwegen", + "hengelaar", + "herkansen", + "hermafrodiet", + "hertaald", + "hiaat", + "hikspoors", + "hitachi", + "hitparade", + "hobo", + "hoeve", + "holocaust", + "hond", + "honnepon", + "hoogacht", + "hotelbed", + "hufter", + "hugo", + "huilbier", + "hulk", + "humus", + "huwbaar", + "huwelijk", + "hype", + "iconisch", + "idema", + "ideogram", + "idolaat", + "ietje", + "ijker", + "ijkheid", + "ijklijn", + "ijkmaat", + "ijkwezen", + "ijmuiden", + "ijsbox", + "ijsdag", + "ijselijk", + "ijskoud", + "ilse", + "immuun", + "impliceer", + "impuls", + "inbijten", + "inbuigen", + "indijken", + "induceer", + "indy", + "infecteer", + "inhaak", + "inkijk", + "inluiden", + "inmijnen", + "inoefenen", + "inpolder", + "inrijden", + "inslaan", + "invitatie", + "inwaaien", + "ionisch", + "isaac", + "isolatie", + "isotherm", + "isra", + "italiaan", + "ivoor", + "jacobs", + "jakob", + "jammen", + "jampot", + "jarig", + "jehova", + "jenever", + "jezus", + "joana", + "jobdienst", + "josua", + "joule", + "juich", + "jurk", + "juut", + "kaas", + "kabelaar", + "kabinet", + "kagenaar", + "kajuit", + "kalebas", + "kalm", + "kanjer", + "kapucijn", + "karregat", + "kart", + "katvanger", + "katwijk", + "kegelaar", + "keiachtig", + "keizer", + "kenletter", + "kerdijk", + "keus", + "kevlar", + "kezen", + "kickback", + "kieviet", + "kijken", + "kikvors", + "kilheid", + "kilobit", + "kilsdonk", + "kipschnitzel", + "kissebis", + "klad", + "klagelijk", + "klak", + "klapbaar", + "klaver", + "klene", + "klets", + "klijnhout", + "klit", + "klok", + "klonen", + "klotefilm", + "kluif", + "klumper", + "klus", + "knabbel", + "knagen", + "knaven", + "kneedbaar", + "knmi", + "knul", + "knus", + "kokhals", + "komiek", + "komkommer", + "kompaan", + "komrij", + "komvormig", + "koning", + "kopbal", + "kopklep", + "kopnagel", + "koppejan", + "koptekst", + "kopwand", + "koraal", + "kosmisch", + "kostbaar", + "kram", + "kraneveld", + "kras", + "kreling", + "krengen", + "kribbe", + "krik", + "kruid", + "krulbol", + "kuijper", + "kuipbank", + "kuit", + "kuiven", + "kutsmoes", + "kuub", + "kwak", + "kwatong", + "kwetsbaar", + "kwezelaar", + "kwijnen", + "kwik", + "kwinkslag", + "kwitantie", + "lading", + "lakbeits", + "lakken", + "laklaag", + "lakmoes", + "lakwijk", + "lamheid", + "lamp", + "lamsbout", + "lapmiddel", + "larve", + "laser", + "latijn", + "latuw", + "lawaai", + "laxeerpil", + "lebberen", + "ledeboer", + "leefbaar", + "leeman", + "lefdoekje", + "lefhebber", + "legboor", + "legsel", + "leguaan", + "leiplaat", + "lekdicht", + "lekrijden", + "leksteen", + "lenen", + "leraar", + "lesbienne", + "leugenaar", + "leut", + "lexicaal", + "lezing", + "lieten", + "liggeld", + "lijdzaam", + "lijk", + "lijmstang", + "lijnschip", + "likdoorn", + "likken", + "liksteen", + "limburg", + "link", + "linoleum", + "lipbloem", + "lipman", + "lispelen", + "lissabon", + "litanie", + "liturgie", + "lochem", + "loempia", + "loesje", + "logheid", + "lonen", + "lonneke", + "loom", + "loos", + "losbaar", + "loslaten", + "losplaats", + "loting", + "lotnummer", + "lots", + "louie", + "lourdes", + "louter", + "lowbudget", + "luijten", + "luikenaar", + "luilak", + "luipaard", + "luizenbos", + "lulkoek", + "lumen", + "lunzen", + "lurven", + "lutjeboer", + "luttel", + "lutz", + "luuk", + "luwte", + "luyendijk", + "lyceum", + "lynx", + "maakbaar", + "magdalena", + "malheid", + "manchet", + "manfred", + "manhaftig", + "mank", + "mantel", + "marion", + "marxist", + "masmeijer", + "massaal", + "matsen", + "matverf", + "matze", + "maude", + "mayonaise", + "mechanica", + "meifeest", + "melodie", + "meppelink", + "midvoor", + "midweeks", + "midzomer", + "miezel", + "mijnraad", + "minus", + "mirck", + "mirte", + "mispakken", + "misraden", + "miswassen", + "mitella", + "moker", + "molecule", + "mombakkes", + "moonen", + "mopperaar", + "moraal", + "morgana", + "mormel", + "mosselaar", + "motregen", + "mouw", + "mufheid", + "mutueel", + "muzelman", + "naaidoos", + "naald", + "nadeel", + "nadruk", + "nagy", + "nahon", + "naima", + "nairobi", + "napalm", + "napels", + "napijn", + "napoleon", + "narigheid", + "narratief", + "naseizoen", + "nasibal", + "navigatie", + "nawijn", + "negatief", + "nekletsel", + "nekwervel", + "neolatijn", + "neonataal", + "neptunus", + "nerd", + "nest", + "neuzelaar", + "nihiliste", + "nijenhuis", + "nijging", + "nijhoff", + "nijl", + "nijptang", + "nippel", + "nokkenas", + "noordam", + "noren", + "normaal", + "nottelman", + "notulant", + "nout", + "nuance", + "nuchter", + "nudorp", + "nulde", + "nullijn", + "nulmeting", + "nunspeet", + "nylon", + "obelisk", + "object", + "oblie", + "obsceen", + "occlusie", + "oceaan", + "ochtend", + "ockhuizen", + "oerdom", + "oergezond", + "oerlaag", + "oester", + "okhuijsen", + "olifant", + "olijfboer", + "omaans", + "ombudsman", + "omdat", + "omdijken", + "omdoen", + "omgebouwd", + "omkeer", + "omkomen", + "ommegaand", + "ommuren", + "omroep", + "omruil", + "omslaan", + "omsmeden", + "omvaar", + "onaardig", + "onedel", + "onenig", + "onheilig", + "onrecht", + "onroerend", + "ontcijfer", + "onthaal", + "ontvallen", + "ontzadeld", + "onzacht", + "onzin", + "onzuiver", + "oogappel", + "ooibos", + "ooievaar", + "ooit", + "oorarts", + "oorhanger", + "oorijzer", + "oorklep", + "oorschelp", + "oorworm", + "oorzaak", + "opdagen", + "opdien", + "opdweilen", + "opel", + "opgebaard", + "opinie", + "opjutten", + "opkijken", + "opklaar", + "opkuisen", + "opkwam", + "opnaaien", + "opossum", + "opsieren", + "opsmeer", + "optreden", + "opvijzel", + "opvlammen", + "opwind", + "oraal", + "orchidee", + "orkest", + "ossuarium", + "ostendorf", + "oublie", + "oudachtig", + "oudbakken", + "oudnoors", + "oudshoorn", + "oudtante", + "oven", + "over", + "oxidant", + "pablo", + "pacht", + "paktafel", + "pakzadel", + "paljas", + "panharing", + "papfles", + "paprika", + "parochie", + "paus", + "pauze", + "paviljoen", + "peek", + "pegel", + "peigeren", + "pekela", + "pendant", + "penibel", + "pepmiddel", + "peptalk", + "periferie", + "perron", + "pessarium", + "peter", + "petfles", + "petgat", + "peuk", + "pfeifer", + "picknick", + "pief", + "pieneman", + "pijlkruid", + "pijnacker", + "pijpelink", + "pikdonker", + "pikeer", + "pilaar", + "pionier", + "pipet", + "piscine", + "pissebed", + "pitchen", + "pixel", + "plamuren", + "plan", + "plausibel", + "plegen", + "plempen", + "pleonasme", + "plezant", + "podoloog", + "pofmouw", + "pokdalig", + "ponywagen", + "popachtig", + "popidool", + "porren", + "positie", + "potten", + "pralen", + "prezen", + "prijzen", + "privaat", + "proef", + "prooi", + "prozawerk", + "pruik", + "prul", + "publiceer", + "puck", + "puilen", + "pukkelig", + "pulveren", + "pupil", + "puppy", + "purmerend", + "pustjens", + "putemmer", + "puzzelaar", + "queenie", + "quiche", + "raam", + "raar", + "raat", + "raes", + "ralf", + "rally", + "ramona", + "ramselaar", + "ranonkel", + "rapen", + "rapunzel", + "rarekiek", + "rarigheid", + "rattenhol", + "ravage", + "reactie", + "recreant", + "redacteur", + "redster", + "reewild", + "regie", + "reijnders", + "rein", + "replica", + "revanche", + "rigide", + "rijbaan", + "rijdansen", + "rijgen", + "rijkdom", + "rijles", + "rijnwijn", + "rijpma", + "rijstafel", + "rijtaak", + "rijzwepen", + "rioleer", + "ripdeal", + "riphagen", + "riskant", + "rits", + "rivaal", + "robbedoes", + "robot", + "rockact", + "rodijk", + "rogier", + "rohypnol", + "rollaag", + "rolpaal", + "roltafel", + "roof", + "roon", + "roppen", + "rosbief", + "rosharig", + "rosielle", + "rotan", + "rotleven", + "rotten", + "rotvaart", + "royaal", + "royeer", + "rubato", + "ruby", + "ruche", + "rudge", + "ruggetje", + "rugnummer", + "rugpijn", + "rugtitel", + "rugzak", + "ruilbaar", + "ruis", + "ruit", + "rukwind", + "rulijs", + "rumoeren", + "rumsdorp", + "rumtaart", + "runnen", + "russchen", + "ruwkruid", + "saboteer", + "saksisch", + "salade", + "salpeter", + "sambabal", + "samsam", + "satelliet", + "satineer", + "saus", + "scampi", + "scarabee", + "scenario", + "schobben", + "schubben", + "scout", + "secessie", + "secondair", + "seculair", + "sediment", + "seeland", + "settelen", + "setwinst", + "sheriff", + "shiatsu", + "siciliaan", + "sidderaal", + "sigma", + "sijben", + "silvana", + "simkaart", + "sinds", + "situatie", + "sjaak", + "sjardijn", + "sjezen", + "sjor", + "skinhead", + "skylab", + "slamixen", + "sleijpen", + "slijkerig", + "slordig", + "slowaak", + "sluieren", + "smadelijk", + "smiecht", + "smoel", + "smos", + "smukken", + "snackcar", + "snavel", + "sneaker", + "sneu", + "snijdbaar", + "snit", + "snorder", + "soapbox", + "soetekouw", + "soigneren", + "sojaboon", + "solo", + "solvabel", + "somber", + "sommatie", + "soort", + "soppen", + "sopraan", + "soundbar", + "spanen", + "spawater", + "spijgat", + "spinaal", + "spionage", + "spiraal", + "spleet", + "splijt", + "spoed", + "sporen", + "spul", + "spuug", + "spuw", + "stalen", + "standaard", + "star", + "stefan", + "stencil", + "stijf", + "stil", + "stip", + "stopdas", + "stoten", + "stoven", + "straat", + "strobbe", + "strubbel", + "stucadoor", + "stuif", + "stukadoor", + "subhoofd", + "subregent", + "sudoku", + "sukade", + "sulfaat", + "surinaams", + "suus", + "syfilis", + "symboliek", + "sympathie", + "synagoge", + "synchroon", + "synergie", + "systeem", + "taanderij", + "tabak", + "tachtig", + "tackelen", + "taiwanees", + "talman", + "tamheid", + "tangaslip", + "taps", + "tarkan", + "tarwe", + "tasman", + "tatjana", + "taxameter", + "teil", + "teisman", + "telbaar", + "telco", + "telganger", + "telstar", + "tenant", + "tepel", + "terzet", + "testament", + "ticket", + "tiesinga", + "tijdelijk", + "tika", + "tiksel", + "tilleman", + "timbaal", + "tinsteen", + "tiplijn", + "tippelaar", + "tjirpen", + "toezeggen", + "tolbaas", + "tolgeld", + "tolhek", + "tolo", + "tolpoort", + "toltarief", + "tolvrij", + "tomaat", + "tondeuse", + "toog", + "tooi", + "toonbaar", + "toos", + "topclub", + "toppen", + "toptalent", + "topvrouw", + "toque", + "torment", + "tornado", + "tosti", + "totdat", + "toucheer", + "toulouse", + "tournedos", + "tout", + "trabant", + "tragedie", + "trailer", + "traject", + "traktaat", + "trauma", + "tray", + "trechter", + "tred", + "tref", + "treur", + "troebel", + "tros", + "trucage", + "truffel", + "tsaar", + "tucht", + "tuenter", + "tuitelig", + "tukje", + "tuktuk", + "tulp", + "tuma", + "tureluurs", + "twijfel", + "twitteren", + "tyfoon", + "typograaf", + "ugandees", + "uiachtig", + "uier", + "uisnipper", + "ultiem", + "unitair", + "uranium", + "urbaan", + "urendag", + "ursula", + "uurcirkel", + "uurglas", + "uzelf", + "vaat", + "vakantie", + "vakleraar", + "valbijl", + "valpartij", + "valreep", + "valuatie", + "vanmiddag", + "vanonder", + "varaan", + "varken", + "vaten", + "veenbes", + "veeteler", + "velgrem", + "vellekoop", + "velvet", + "veneberg", + "venlo", + "vent", + "venusberg", + "venw", + "veredeld", + "verf", + "verhaaf", + "vermaak", + "vernaaid", + "verraad", + "vers", + "veruit", + "verzaagd", + "vetachtig", + "vetlok", + "vetmesten", + "veto", + "vetrek", + "vetstaart", + "vetten", + "veurink", + "viaduct", + "vibrafoon", + "vicariaat", + "vieux", + "vieveen", + "vijfvoud", + "villa", + "vilt", + "vimmetje", + "vindbaar", + "vips", + "virtueel", + "visdieven", + "visee", + "visie", + "vlaag", + "vleugel", + "vmbo", + "vocht", + "voesenek", + "voicemail", + "voip", + "volg", + "vork", + "vorselaar", + "voyeur", + "vracht", + "vrekkig", + "vreten", + "vrije", + "vrozen", + "vrucht", + "vucht", + "vugt", + "vulkaan", + "vulmiddel", + "vulva", + "vuren", + "waas", + "wacht", + "wadvogel", + "wafel", + "waffel", + "walhalla", + "walnoot", + "walraven", + "wals", + "walvis", + "wandaad", + "wanen", + "wanmolen", + "want", + "warklomp", + "warm", + "wasachtig", + "wasteil", + "watt", + "webhandel", + "weblog", + "webpagina", + "webzine", + "wedereis", + "wedstrijd", + "weeda", + "weert", + "wegmaaien", + "wegscheer", + "wekelijks", + "wekken", + "wekroep", + "wektoon", + "weldaad", + "welwater", + "wendbaar", + "wenkbrauw", + "wens", + "wentelaar", + "wervel", + "wesseling", + "wetboek", + "wetmatig", + "whirlpool", + "wijbrands", + "wijdbeens", + "wijk", + "wijnbes", + "wijting", + "wild", + "wimpelen", + "wingebied", + "winplaats", + "winter", + "winzucht", + "wipstaart", + "wisgerhof", + "withaar", + "witmaker", + "wokkel", + "wolf", + "wonenden", + "woning", + "worden", + "worp", + "wortel", + "wrat", + "wrijf", + "wringen", + "yoghurt", + "ypsilon", + "zaaijer", + "zaak", + "zacharias", + "zakelijk", + "zakkam", + "zakwater", + "zalf", + "zalig", + "zaniken", + "zebracode", + "zeeblauw", + "zeef", + "zeegaand", + "zeeuw", + "zege", + "zegje", + "zeil", + "zesbaans", + "zesenhalf", + "zeskantig", + "zesmaal", + "zetbaas", + "zetpil", + "zeulen", + "ziezo", + "zigzag", + "zijaltaar", + "zijbeuk", + "zijlijn", + "zijmuur", + "zijn", + "zijwaarts", + "zijzelf", + "zilt", + "zimmerman", + "zinledig", + "zinnelijk", + "zionist", + "zitdag", + "zitruimte", + "zitzak", + "zoal", + "zodoende", + "zoekbots", + "zoem", + "zoiets", + "zojuist", + "zondaar", + "zotskap", + "zottebol", + "zucht", + "zuivel", + "zulk", + "zult", + "zuster", + "zuur", + "zweedijk", + "zwendel", + "zwepen", + "zwiep", + "zwijmel", + "zworen" + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/electrum-words.cpp b/src/Mnemonics/electrum-words.cpp new file mode 100644 index 0000000..d929f01 --- /dev/null +++ b/src/Mnemonics/electrum-words.cpp @@ -0,0 +1,471 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file electrum-words.cpp + * + * \brief Mnemonic seed generation and wallet restoration from them. + * + * 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 +#include +#include +#include +#include +#include +#include "crypto/crypto.h" // for declaration of crypto::secret_key +#include +#include "Mnemonics/electrum-words.h" +#include +#include +#include +#include + +namespace +{ + uint32_t create_checksum_index(const std::vector &word_list, + uint32_t unique_prefix_length); + bool checksum_test(std::vector seed, uint32_t unique_prefix_length); + + /*! + * \brief Finds the word list that contains the seed words and puts the indices + * where matches occured in matched_indices. + * \param seed List of words to match. + * \param has_checksum The seed has a checksum word (maybe not checked). + * \param matched_indices The indices where the seed words were found are added to this. + * \param language Language instance pointer to write to after it is found. + * \return true if all the words were present in some language false if not. + */ + bool find_seed_language(const std::vector &seed, + bool has_checksum, std::vector &matched_indices, Language::Base **language) + { + // If there's a new language added, add an instance of it here. + std::vector language_instances({ + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance() + }); + Language::Base *fallback = NULL; + + // Iterate through all the languages and find a match + for (std::vector::iterator it1 = language_instances.begin(); + it1 != language_instances.end(); it1++) + { + const std::unordered_map &word_map = (*it1)->get_word_map(); + const std::unordered_map &trimmed_word_map = (*it1)->get_trimmed_word_map(); + // To iterate through seed words + std::vector::const_iterator it2; + bool full_match = true; + + std::string trimmed_word; + // Iterate through all the words and see if they're all present + for (it2 = seed.begin(); it2 != seed.end(); it2++) + { + if (has_checksum) + { + trimmed_word = Language::utf8prefix(*it2, (*it1)->get_unique_prefix_length()); + // Use the trimmed words and map + if (trimmed_word_map.count(trimmed_word) == 0) + { + full_match = false; + break; + } + matched_indices.push_back(trimmed_word_map.at(trimmed_word)); + } + else + { + if (word_map.count(*it2) == 0) + { + full_match = false; + break; + } + matched_indices.push_back(word_map.at(*it2)); + } + } + if (full_match) + { + // if we were using prefix only, and we have a checksum, check it now + // to avoid false positives due to prefix set being too common + if (has_checksum) + if (!checksum_test(seed, (*it1)->get_unique_prefix_length())) + { + fallback = *it1; + full_match = false; + } + } + if (full_match) + { + *language = *it1; + return true; + } + // Some didn't match. Clear the index array. + matched_indices.clear(); + } + + // if we get there, we've not found a good match, but we might have a fallback, + // if we detected a match which did not fit the checksum, which might be a badly + // typed/transcribed seed in the right language + if (fallback) + { + *language = fallback; + return true; + } + + return false; + } + + /*! + * \brief Creates a checksum index in the word list array on the list of words. + * \param word_list Vector of words + * \param unique_prefix_length the prefix length of each word to use for checksum + * \return Checksum index + */ + uint32_t create_checksum_index(const std::vector &word_list, + uint32_t unique_prefix_length) + { + std::string trimmed_words = ""; + + for (std::vector::const_iterator it = word_list.begin(); it != word_list.end(); it++) + { + if (it->length() > unique_prefix_length) + { + trimmed_words += Language::utf8prefix(*it, unique_prefix_length); + } + else + { + trimmed_words += *it; + } + } + boost::crc_32_type result; + result.process_bytes(trimmed_words.data(), trimmed_words.length()); + return result.checksum() % crypto::ElectrumWords::seed_length; + } + + /*! + * \brief Does the checksum test on the seed passed. + * \param seed Vector of seed words + * \param unique_prefix_length the prefix length of each word to use for checksum + * \return True if the test passed false if not. + */ + bool checksum_test(std::vector seed, uint32_t unique_prefix_length) + { + if (seed.empty()) + return false; + // The last word is the checksum. + std::string last_word = seed.back(); + seed.pop_back(); + + std::string checksum = seed[create_checksum_index(seed, unique_prefix_length)]; + + std::string trimmed_checksum = checksum.length() > unique_prefix_length ? Language::utf8prefix(checksum, unique_prefix_length) : + checksum; + std::string trimmed_last_word = last_word.length() > unique_prefix_length ? Language::utf8prefix(last_word, unique_prefix_length) : + last_word; + return trimmed_checksum == trimmed_last_word; + } +} + +/*! + * \namespace crypto + * + * \brief crypto namespace. + */ +namespace crypto +{ + /*! + * \namespace crypto::ElectrumWords + * + * \brief Mnemonic seed word generation and wallet restoration helper functions. + */ + namespace ElectrumWords + { + /*! + * \brief Converts seed words to bytes (secret key). + * \param words String containing the words separated by spaces. + * \param dst To put the secret data restored from the words. + * \param len The number of bytes to expect, 0 if unknown + * \param duplicate If true and len is not zero, we accept half the data, and duplicate it + * \param language_name Language of the seed as found gets written here. + * \return false if not a multiple of 3 words, or if word is not in the words list + */ + bool words_to_bytes(std::string words, std::string& dst, size_t len, bool duplicate, + std::string &language_name) + { + std::vector seed; + + boost::algorithm::trim(words); + boost::split(seed, words, boost::is_any_of(" "), boost::token_compress_on); + + if (len % 4) + return false; + + bool has_checksum = true; + if (len) + { + // error on non-compliant word list + const size_t expected = len * 8 * 3 / 32; + if (seed.size() != expected/2 && seed.size() != expected && + seed.size() != expected + 1) + { + return false; + } + + // If it is seed with a checksum. + has_checksum = seed.size() == (expected + 1); + } + + std::vector matched_indices; + Language::Base *language; + if (!find_seed_language(seed, has_checksum, matched_indices, &language)) + { + return false; + } + language_name = language->get_language_name(); + uint32_t word_list_length = static_cast(language->get_word_list().size()); + + if (has_checksum) + { + if (!checksum_test(seed, language->get_unique_prefix_length())) + { + // Checksum fail + return false; + } + seed.pop_back(); + } + + for (unsigned int i=0; i < seed.size() / 3; i++) + { + uint32_t val; + uint32_t w1, w2, w3; + w1 = matched_indices[i*3]; + w2 = matched_indices[i*3 + 1]; + w3 = matched_indices[i*3 + 2]; + + val = w1 + word_list_length * (((word_list_length - w1) + w2) % word_list_length) + + word_list_length * word_list_length * (((word_list_length - w2) + w3) % word_list_length); + + if (!(val % word_list_length == w1)) return false; + + dst.append((const char*)&val, 4); // copy 4 bytes to position + } + + if (len > 0 && duplicate) + { + const size_t expected = len * 3 / 32; + std::string wlist_copy = words; + if (seed.size() == expected/2) + { + dst.append(dst); // if electrum 12-word seed, duplicate + wlist_copy += ' '; + wlist_copy += words; + } + } + + return true; + } + + /*! + * \brief Converts seed words to bytes (secret key). + * \param words String containing the words separated by spaces. + * \param dst To put the secret key restored from the words. + * \param language_name Language of the seed as found gets written here. + * \return false if not a multiple of 3 words, or if word is not in the words list + */ + bool words_to_bytes(std::string words, Crypto::SecretKey& dst, + std::string &language_name) + { + std::string s; + if (!words_to_bytes(words, s, sizeof(dst), true, language_name)) + return false; + if (s.size() != sizeof(dst)) + return false; + dst = *(const Crypto::SecretKey*)s.data(); + return true; + } + + /*! + * \brief Converts bytes (secret key) to seed words. + * \param src Secret key + * \param words Space delimited concatenated words get written here. + * \param language_name Seed language name + * \return true if successful false if not. Unsuccessful if wrong key size. + */ + bool bytes_to_words(const char *src, size_t len, std::string& words, + const std::string &language_name) + { + + if (len % 4 != 0 || len == 0) return false; + + Language::Base *language; + if (language_name == "English") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Nederlands") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Français") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Español") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Português") + { + language = Language::Singleton::instance(); + } + else if (language_name == "日本語") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Italiano") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Deutsch") + { + language = Language::Singleton::instance(); + } + else if (language_name == "русский язык") + { + language = Language::Singleton::instance(); + } + else if (language_name == "简体中文 (中国)") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Esperanto") + { + language = Language::Singleton::instance(); + } + else if (language_name == "Lojban") + { + language = Language::Singleton::instance(); + } + else + { + return false; + } + const std::vector &word_list = language->get_word_list(); + // To store the words for random access to add the checksum word later. + std::vector words_store; + + uint32_t word_list_length = static_cast(word_list.size()); + // 4 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626 + for (unsigned int i=0; i < len/4; i++, words += ' ') + { + uint32_t w1, w2, w3; + + uint32_t val; + + memcpy(&val, src + (i * 4), 4); + + w1 = val % word_list_length; + w2 = ((val / word_list_length) + w1) % word_list_length; + w3 = (((val / word_list_length) / word_list_length) + w2) % word_list_length; + + words += word_list[w1]; + words += ' '; + words += word_list[w2]; + words += ' '; + words += word_list[w3]; + + words_store.push_back(word_list[w1]); + words_store.push_back(word_list[w2]); + words_store.push_back(word_list[w3]); + } + + words.pop_back(); + words += (' ' + words_store[create_checksum_index(words_store, language->get_unique_prefix_length())]); + return true; + } + + bool bytes_to_words(const Crypto::SecretKey& src, std::string& words, + const std::string &language_name) + { + return bytes_to_words(reinterpret_cast(src.data), sizeof(src), words, language_name); + } + + /*! + * \brief Gets a list of seed languages that are supported. + * \param languages The vector is set to the list of languages. + */ + void get_language_list(std::vector &languages) + { + std::vector language_instances({ + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance(), + Language::Singleton::instance() + }); + for (std::vector::iterator it = language_instances.begin(); + it != language_instances.end(); it++) + { + languages.push_back((*it)->get_language_name()); + } + } + + /*! + * \brief Tells if the seed passed is an old style seed or not. + * \param seed The seed to check (a space delimited concatenated word list) + * \return true if the seed passed is a old style seed false if not. + */ + bool get_is_old_style_seed(std::string seed) + { + std::vector word_list; + boost::algorithm::trim(seed); + boost::split(word_list, seed, boost::is_any_of(" "), boost::token_compress_on); + return word_list.size() != (seed_length + 1); + } + } +} diff --git a/src/Mnemonics/electrum-words.h b/src/Mnemonics/electrum-words.h new file mode 100644 index 0000000..9f1d23e --- /dev/null +++ b/src/Mnemonics/electrum-words.h @@ -0,0 +1,249 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file electrum-words.h + * + * \brief Mnemonic seed generation and wallet restoration from them. + * + * 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. + */ + +#ifndef ELECTRUM_WORDS_H +#define ELECTRUM_WORDS_H + +#include +#include +#include +#include +#include +#include +#include "crypto/crypto.h" // for declaration of crypto::secret_key + +#include "chinese_simplified.h" +#include "english.h" +#include "dutch.h" +#include "french.h" +#include "italian.h" +#include "german.h" +#include "spanish.h" +#include "portuguese.h" +#include "japanese.h" +#include "russian.h" +#include "esperanto.h" +#include "lojban.h" +#include "english_old.h" +#include "language_base.h" +#include "singleton.h" + +/*! + * \namespace crypto + * + * \brief crypto namespace. + */ +namespace crypto +{ + /*! + * \namespace crypto::ElectrumWords + * + * \brief Mnemonic seed word generation and wallet restoration helper functions. + */ + namespace ElectrumWords + { + + const int seed_length = 24; + const std::string old_language_name = "EnglishOld"; + /*! + * \brief Converts seed words to bytes (secret key). + * \param words String containing the words separated by spaces. + * \param dst To put the secret data restored from the words. + * \param len The number of bytes to expect, 0 if unknown + * \param duplicate If true and len is not zero, we accept half the data, and duplicate it + * \param language_name Language of the seed as found gets written here. + * \return false if not a multiple of 3 words, or if word is not in the words list + */ + bool words_to_bytes(std::string words, std::string& dst, size_t len, bool duplicate, + std::string &language_name); + /*! + * \brief Converts seed words to bytes (secret key). + * \param words String containing the words separated by spaces. + * \param dst To put the secret key restored from the words. + * \param language_name Language of the seed as found gets written here. + * \return false if not a multiple of 3 words, or if word is not in the words list + */ + bool words_to_bytes(std::string words, Crypto::SecretKey& dst, + std::string &language_name); + + /*! + * \brief Converts bytes to seed words. + * \param src Secret data + * \param len Secret data length in bytes (positive multiples of 4 only) + * \param words Space delimited concatenated words get written here. + * \param language_name Seed language name + * \return true if successful false if not. Unsuccessful if wrong key size. + */ + bool bytes_to_words(const char *src, size_t len, std::string& words, + const std::string &language_name); + + /*! + * \brief Converts bytes (secret key) to seed words. + * \param src Secret key + * \param words Space delimited concatenated words get written here. + * \param language_name Seed language name + * \return true if successful false if not. Unsuccessful if wrong key size. + */ + bool bytes_to_words(const Crypto::SecretKey& src, std::string& words, + const std::string &language_name); + + /*! + * \brief Gets a list of seed languages that are supported. + * \param languages A vector is set to the list of languages. + */ + void get_language_list(std::vector &languages); + + /*! + * \brief Tells if the seed passed is an old style seed or not. + * \param seed The seed to check (a space delimited concatenated word list) + * \return true if the seed passed is a old style seed false if not. + */ + bool get_is_old_style_seed(std::string seed); + + /* Templates have to be implemented in the header to be accessible + elsewhere */ + + /*! + * \brief Logs words not present in the english word list. + * \param words The words to check if they are present in the dictionary + * \param stream A type implementing << to have output written to + */ + template + void log_incorrect_words(std::vector words, T &stream) + { + Language::Base *language = Language::Singleton::instance(); + const std::vector &dictionary = language->get_word_list(); + + Common::Console::setTextColor(Common::Console::Color::BrightRed); + + for (auto i : words) + { + if (std::find(dictionary.begin(), dictionary.end(), i) == dictionary.end()) + { + stream << i << " is not in the english word list!" << std::endl; + } + } + + Common::Console::setTextColor(Common::Console::Color::Default); + } + + /*! + * \brief Parses a seed into a private spend key if possible. + * \param mnemonic_phrase The mnemonic string to parse (a space delimited concatenated word list) + * \param private_spend_key The secret key to parse the mnemonic seed into + * \param stream A type implementing << to have output written to + * \return true if the mnemonic could be parsed + */ + template + bool is_valid_mnemonic(std::string mnemonic_phrase, + Crypto::SecretKey &private_spend_key, + T &stream) + + { + /* Uncommenting these will allow importing of different languages, exporting + in different languages however has not been added, as it will require + changing the export_keys command to take an argument to specify what + language the seed should be exported in. For now, multilanguage support + has been disabled as there are a couple of issues - we can't print out + what words aren't present in the dictionary if we don't know what + dictionary they are using, and it's a lot more friendly to work that + out automatically rather than asking, and secondly, it is possible that + dictionaries of other words can overlap enough to allow an esperanto + seed for example to be imported as an english seed */ + + /* + static std::string languages[] = {"English", "Nederlands", "Français", + "Português", "Italiano", "Deutsch", + "русский язык", "简体中文 (中国)", + "Esperanto", "Lojban"}; + + static const int num_of_languages = 10; + */ + + static std::string languages[] = {"English"}; + + static const int num_of_languages = 1; + + static const int mnemonic_phrase_length = 25; + + std::vector words; + + words = boost::split(words, mnemonic_phrase, ::isspace); + + if (words.size() != mnemonic_phrase_length) + { + Common::Console::setTextColor(Common::Console::Color::BrightRed); + stream << "Invalid mnemonic phrase! Seed phrase is not 25 words! " + << "Please try again." << std::endl; + + log_incorrect_words(words, stream); + + Common::Console::setTextColor(Common::Console::Color::Default); + + return false; + } + + /* Check every language for our phrase so the user doesn't have to specify + it, this shouldn't be an issue as long as one language doesn't have enough + of another languages words, might need some testing */ + for (int i = 0; i < num_of_languages; i++) + { + if (words_to_bytes(mnemonic_phrase, private_spend_key, languages[i])) + { + return true; + } + } + + /* The issue with this is if we try and automagically determine what language + the seed phrase is in, then we can't log words which aren't in the x + dictionary, we will have to take an argument to know what language they + are in, but this is less user friendly. */ + Common::Console::setTextColor(Common::Console::Color::BrightRed); + + stream << "Invalid mnemonic phrase!" << std::endl; + + Common::Console::setTextColor(Common::Console::Color::Default); + + log_incorrect_words(words, stream); + + return false; + } + } +} + +#endif diff --git a/src/Mnemonics/english.h b/src/Mnemonics/english.h new file mode 100644 index 0000000..9d7d8a0 --- /dev/null +++ b/src/Mnemonics/english.h @@ -0,0 +1,1686 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file english.h + * + * \brief New English word list and map. + */ + +#ifndef ENGLISH_H +#define ENGLISH_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class English: public Base + { + public: + English(): Base("English", std::vector({ + "abbey", + "abducts", + "ability", + "ablaze", + "abnormal", + "abort", + "abrasive", + "absorb", + "abyss", + "academy", + "aces", + "aching", + "acidic", + "acoustic", + "acquire", + "across", + "actress", + "acumen", + "adapt", + "addicted", + "adept", + "adhesive", + "adjust", + "adopt", + "adrenalin", + "adult", + "adventure", + "aerial", + "afar", + "affair", + "afield", + "afloat", + "afoot", + "afraid", + "after", + "against", + "agenda", + "aggravate", + "agile", + "aglow", + "agnostic", + "agony", + "agreed", + "ahead", + "aided", + "ailments", + "aimless", + "airport", + "aisle", + "ajar", + "akin", + "alarms", + "album", + "alchemy", + "alerts", + "algebra", + "alkaline", + "alley", + "almost", + "aloof", + "alpine", + "already", + "also", + "altitude", + "alumni", + "always", + "amaze", + "ambush", + "amended", + "amidst", + "ammo", + "amnesty", + "among", + "amply", + "amused", + "anchor", + "android", + "anecdote", + "angled", + "ankle", + "annoyed", + "answers", + "antics", + "anvil", + "anxiety", + "anybody", + "apart", + "apex", + "aphid", + "aplomb", + "apology", + "apply", + "apricot", + "aptitude", + "aquarium", + "arbitrary", + "archer", + "ardent", + "arena", + "argue", + "arises", + "army", + "around", + "arrow", + "arsenic", + "artistic", + "ascend", + "ashtray", + "aside", + "asked", + "asleep", + "aspire", + "assorted", + "asylum", + "athlete", + "atlas", + "atom", + "atrium", + "attire", + "auburn", + "auctions", + "audio", + "august", + "aunt", + "austere", + "autumn", + "avatar", + "avidly", + "avoid", + "awakened", + "awesome", + "awful", + "awkward", + "awning", + "awoken", + "axes", + "axis", + "axle", + "aztec", + "azure", + "baby", + "bacon", + "badge", + "baffles", + "bagpipe", + "bailed", + "bakery", + "balding", + "bamboo", + "banjo", + "baptism", + "basin", + "batch", + "bawled", + "bays", + "because", + "beer", + "befit", + "begun", + "behind", + "being", + "below", + "bemused", + "benches", + "berries", + "bested", + "betting", + "bevel", + "beware", + "beyond", + "bias", + "bicycle", + "bids", + "bifocals", + "biggest", + "bikini", + "bimonthly", + "binocular", + "biology", + "biplane", + "birth", + "biscuit", + "bite", + "biweekly", + "blender", + "blip", + "bluntly", + "boat", + "bobsled", + "bodies", + "bogeys", + "boil", + "boldly", + "bomb", + "border", + "boss", + "both", + "bounced", + "bovine", + "bowling", + "boxes", + "boyfriend", + "broken", + "brunt", + "bubble", + "buckets", + "budget", + "buffet", + "bugs", + "building", + "bulb", + "bumper", + "bunch", + "business", + "butter", + "buying", + "buzzer", + "bygones", + "byline", + "bypass", + "cabin", + "cactus", + "cadets", + "cafe", + "cage", + "cajun", + "cake", + "calamity", + "camp", + "candy", + "casket", + "catch", + "cause", + "cavernous", + "cease", + "cedar", + "ceiling", + "cell", + "cement", + "cent", + "certain", + "chlorine", + "chrome", + "cider", + "cigar", + "cinema", + "circle", + "cistern", + "citadel", + "civilian", + "claim", + "click", + "clue", + "coal", + "cobra", + "cocoa", + "code", + "coexist", + "coffee", + "cogs", + "cohesive", + "coils", + "colony", + "comb", + "cool", + "copy", + "corrode", + "costume", + "cottage", + "cousin", + "cowl", + "criminal", + "cube", + "cucumber", + "cuddled", + "cuffs", + "cuisine", + "cunning", + "cupcake", + "custom", + "cycling", + "cylinder", + "cynical", + "dabbing", + "dads", + "daft", + "dagger", + "daily", + "damp", + "dangerous", + "dapper", + "darted", + "dash", + "dating", + "dauntless", + "dawn", + "daytime", + "dazed", + "debut", + "decay", + "dedicated", + "deepest", + "deftly", + "degrees", + "dehydrate", + "deity", + "dejected", + "delayed", + "demonstrate", + "dented", + "deodorant", + "depth", + "desk", + "devoid", + "dewdrop", + "dexterity", + "dialect", + "dice", + "diet", + "different", + "digit", + "dilute", + "dime", + "dinner", + "diode", + "diplomat", + "directed", + "distance", + "ditch", + "divers", + "dizzy", + "doctor", + "dodge", + "does", + "dogs", + "doing", + "dolphin", + "domestic", + "donuts", + "doorway", + "dormant", + "dosage", + "dotted", + "double", + "dove", + "down", + "dozen", + "dreams", + "drinks", + "drowning", + "drunk", + "drying", + "dual", + "dubbed", + "duckling", + "dude", + "duets", + "duke", + "dullness", + "dummy", + "dunes", + "duplex", + "duration", + "dusted", + "duties", + "dwarf", + "dwelt", + "dwindling", + "dying", + "dynamite", + "dyslexic", + "each", + "eagle", + "earth", + "easy", + "eating", + "eavesdrop", + "eccentric", + "echo", + "eclipse", + "economics", + "ecstatic", + "eden", + "edgy", + "edited", + "educated", + "eels", + "efficient", + "eggs", + "egotistic", + "eight", + "either", + "eject", + "elapse", + "elbow", + "eldest", + "eleven", + "elite", + "elope", + "else", + "eluded", + "emails", + "ember", + "emerge", + "emit", + "emotion", + "empty", + "emulate", + "energy", + "enforce", + "enhanced", + "enigma", + "enjoy", + "enlist", + "enmity", + "enough", + "enraged", + "ensign", + "entrance", + "envy", + "epoxy", + "equip", + "erase", + "erected", + "erosion", + "error", + "eskimos", + "espionage", + "essential", + "estate", + "etched", + "eternal", + "ethics", + "etiquette", + "evaluate", + "evenings", + "evicted", + "evolved", + "examine", + "excess", + "exhale", + "exit", + "exotic", + "exquisite", + "extra", + "exult", + "fabrics", + "factual", + "fading", + "fainted", + "faked", + "fall", + "family", + "fancy", + "farming", + "fatal", + "faulty", + "fawns", + "faxed", + "fazed", + "feast", + "february", + "federal", + "feel", + "feline", + "females", + "fences", + "ferry", + "festival", + "fetches", + "fever", + "fewest", + "fiat", + "fibula", + "fictional", + "fidget", + "fierce", + "fifteen", + "fight", + "films", + "firm", + "fishing", + "fitting", + "five", + "fixate", + "fizzle", + "fleet", + "flippant", + "flying", + "foamy", + "focus", + "foes", + "foggy", + "foiled", + "folding", + "fonts", + "foolish", + "fossil", + "fountain", + "fowls", + "foxes", + "foyer", + "framed", + "friendly", + "frown", + "fruit", + "frying", + "fudge", + "fuel", + "fugitive", + "fully", + "fuming", + "fungal", + "furnished", + "fuselage", + "future", + "fuzzy", + "gables", + "gadget", + "gags", + "gained", + "galaxy", + "gambit", + "gang", + "gasp", + "gather", + "gauze", + "gave", + "gawk", + "gaze", + "gearbox", + "gecko", + "geek", + "gels", + "gemstone", + "general", + "geometry", + "germs", + "gesture", + "getting", + "geyser", + "ghetto", + "ghost", + "giant", + "giddy", + "gifts", + "gigantic", + "gills", + "gimmick", + "ginger", + "girth", + "giving", + "glass", + "gleeful", + "glide", + "gnaw", + "gnome", + "goat", + "goblet", + "godfather", + "goes", + "goggles", + "going", + "goldfish", + "gone", + "goodbye", + "gopher", + "gorilla", + "gossip", + "gotten", + "gourmet", + "governing", + "gown", + "greater", + "grunt", + "guarded", + "guest", + "guide", + "gulp", + "gumball", + "guru", + "gusts", + "gutter", + "guys", + "gymnast", + "gypsy", + "gyrate", + "habitat", + "hacksaw", + "haggled", + "hairy", + "hamburger", + "happens", + "hashing", + "hatchet", + "haunted", + "having", + "hawk", + "haystack", + "hazard", + "hectare", + "hedgehog", + "heels", + "hefty", + "height", + "hemlock", + "hence", + "heron", + "hesitate", + "hexagon", + "hickory", + "hiding", + "highway", + "hijack", + "hiker", + "hills", + "himself", + "hinder", + "hippo", + "hire", + "history", + "hitched", + "hive", + "hoax", + "hobby", + "hockey", + "hoisting", + "hold", + "honked", + "hookup", + "hope", + "hornet", + "hospital", + "hotel", + "hounded", + "hover", + "howls", + "hubcaps", + "huddle", + "huge", + "hull", + "humid", + "hunter", + "hurried", + "husband", + "huts", + "hybrid", + "hydrogen", + "hyper", + "iceberg", + "icing", + "icon", + "identity", + "idiom", + "idled", + "idols", + "igloo", + "ignore", + "iguana", + "illness", + "imagine", + "imbalance", + "imitate", + "impel", + "inactive", + "inbound", + "incur", + "industrial", + "inexact", + "inflamed", + "ingested", + "initiate", + "injury", + "inkling", + "inline", + "inmate", + "innocent", + "inorganic", + "input", + "inquest", + "inroads", + "insult", + "intended", + "inundate", + "invoke", + "inwardly", + "ionic", + "irate", + "iris", + "irony", + "irritate", + "island", + "isolated", + "issued", + "italics", + "itches", + "items", + "itinerary", + "itself", + "ivory", + "jabbed", + "jackets", + "jaded", + "jagged", + "jailed", + "jamming", + "january", + "jargon", + "jaunt", + "javelin", + "jaws", + "jazz", + "jeans", + "jeers", + "jellyfish", + "jeopardy", + "jerseys", + "jester", + "jetting", + "jewels", + "jigsaw", + "jingle", + "jittery", + "jive", + "jobs", + "jockey", + "jogger", + "joining", + "joking", + "jolted", + "jostle", + "journal", + "joyous", + "jubilee", + "judge", + "juggled", + "juicy", + "jukebox", + "july", + "jump", + "junk", + "jury", + "justice", + "juvenile", + "kangaroo", + "karate", + "keep", + "kennel", + "kept", + "kernels", + "kettle", + "keyboard", + "kickoff", + "kidneys", + "king", + "kiosk", + "kisses", + "kitchens", + "kiwi", + "knapsack", + "knee", + "knife", + "knowledge", + "knuckle", + "koala", + "laboratory", + "ladder", + "lagoon", + "lair", + "lakes", + "lamb", + "language", + "laptop", + "large", + "last", + "later", + "launching", + "lava", + "lawsuit", + "layout", + "lazy", + "lectures", + "ledge", + "leech", + "left", + "legion", + "leisure", + "lemon", + "lending", + "leopard", + "lesson", + "lettuce", + "lexicon", + "liar", + "library", + "licks", + "lids", + "lied", + "lifestyle", + "light", + "likewise", + "lilac", + "limits", + "linen", + "lion", + "lipstick", + "liquid", + "listen", + "lively", + "loaded", + "lobster", + "locker", + "lodge", + "lofty", + "logic", + "loincloth", + "long", + "looking", + "lopped", + "lordship", + "losing", + "lottery", + "loudly", + "love", + "lower", + "loyal", + "lucky", + "luggage", + "lukewarm", + "lullaby", + "lumber", + "lunar", + "lurk", + "lush", + "luxury", + "lymph", + "lynx", + "lyrics", + "macro", + "madness", + "magically", + "mailed", + "major", + "makeup", + "malady", + "mammal", + "maps", + "masterful", + "match", + "maul", + "maverick", + "maximum", + "mayor", + "maze", + "meant", + "mechanic", + "medicate", + "meeting", + "megabyte", + "melting", + "memoir", + "menu", + "merger", + "mesh", + "metro", + "mews", + "mice", + "midst", + "mighty", + "mime", + "mirror", + "misery", + "mittens", + "mixture", + "moat", + "mobile", + "mocked", + "mohawk", + "moisture", + "molten", + "moment", + "money", + "moon", + "mops", + "morsel", + "mostly", + "motherly", + "mouth", + "movement", + "mowing", + "much", + "muddy", + "muffin", + "mugged", + "mullet", + "mumble", + "mundane", + "muppet", + "mural", + "musical", + "muzzle", + "myriad", + "mystery", + "myth", + "nabbing", + "nagged", + "nail", + "names", + "nanny", + "napkin", + "narrate", + "nasty", + "natural", + "nautical", + "navy", + "nearby", + "necklace", + "needed", + "negative", + "neither", + "neon", + "nephew", + "nerves", + "nestle", + "network", + "neutral", + "never", + "newt", + "nexus", + "nibs", + "niche", + "niece", + "nifty", + "nightly", + "nimbly", + "nineteen", + "nirvana", + "nitrogen", + "nobody", + "nocturnal", + "nodes", + "noises", + "nomad", + "noodles", + "northern", + "nostril", + "noted", + "nouns", + "novelty", + "nowhere", + "nozzle", + "nuance", + "nucleus", + "nudged", + "nugget", + "nuisance", + "null", + "number", + "nuns", + "nurse", + "nutshell", + "nylon", + "oaks", + "oars", + "oasis", + "oatmeal", + "obedient", + "object", + "obliged", + "obnoxious", + "observant", + "obtains", + "obvious", + "occur", + "ocean", + "october", + "odds", + "odometer", + "offend", + "often", + "oilfield", + "ointment", + "okay", + "older", + "olive", + "olympics", + "omega", + "omission", + "omnibus", + "onboard", + "oncoming", + "oneself", + "ongoing", + "onion", + "online", + "onslaught", + "onto", + "onward", + "oozed", + "opacity", + "opened", + "opposite", + "optical", + "opus", + "orange", + "orbit", + "orchid", + "orders", + "organs", + "origin", + "ornament", + "orphans", + "oscar", + "ostrich", + "otherwise", + "otter", + "ouch", + "ought", + "ounce", + "ourselves", + "oust", + "outbreak", + "oval", + "oven", + "owed", + "owls", + "owner", + "oxidant", + "oxygen", + "oyster", + "ozone", + "pact", + "paddles", + "pager", + "pairing", + "palace", + "pamphlet", + "pancakes", + "paper", + "paradise", + "pastry", + "patio", + "pause", + "pavements", + "pawnshop", + "payment", + "peaches", + "pebbles", + "peculiar", + "pedantic", + "peeled", + "pegs", + "pelican", + "pencil", + "people", + "pepper", + "perfect", + "pests", + "petals", + "phase", + "pheasants", + "phone", + "phrases", + "physics", + "piano", + "picked", + "pierce", + "pigment", + "piloted", + "pimple", + "pinched", + "pioneer", + "pipeline", + "pirate", + "pistons", + "pitched", + "pivot", + "pixels", + "pizza", + "playful", + "pledge", + "pliers", + "plotting", + "plus", + "plywood", + "poaching", + "pockets", + "podcast", + "poetry", + "point", + "poker", + "polar", + "ponies", + "pool", + "popular", + "portents", + "possible", + "potato", + "pouch", + "poverty", + "powder", + "pram", + "present", + "pride", + "problems", + "pruned", + "prying", + "psychic", + "public", + "puck", + "puddle", + "puffin", + "pulp", + "pumpkins", + "punch", + "puppy", + "purged", + "push", + "putty", + "puzzled", + "pylons", + "pyramid", + "python", + "queen", + "quick", + "quote", + "rabbits", + "racetrack", + "radar", + "rafts", + "rage", + "railway", + "raking", + "rally", + "ramped", + "randomly", + "rapid", + "rarest", + "rash", + "rated", + "ravine", + "rays", + "razor", + "react", + "rebel", + "recipe", + "reduce", + "reef", + "refer", + "regular", + "reheat", + "reinvest", + "rejoices", + "rekindle", + "relic", + "remedy", + "renting", + "reorder", + "repent", + "request", + "reruns", + "rest", + "return", + "reunion", + "revamp", + "rewind", + "rhino", + "rhythm", + "ribbon", + "richly", + "ridges", + "rift", + "rigid", + "rims", + "ringing", + "riots", + "ripped", + "rising", + "ritual", + "river", + "roared", + "robot", + "rockets", + "rodent", + "rogue", + "roles", + "romance", + "roomy", + "roped", + "roster", + "rotate", + "rounded", + "rover", + "rowboat", + "royal", + "ruby", + "rudely", + "ruffled", + "rugged", + "ruined", + "ruling", + "rumble", + "runway", + "rural", + "rustled", + "ruthless", + "sabotage", + "sack", + "sadness", + "safety", + "saga", + "sailor", + "sake", + "salads", + "sample", + "sanity", + "sapling", + "sarcasm", + "sash", + "satin", + "saucepan", + "saved", + "sawmill", + "saxophone", + "sayings", + "scamper", + "scenic", + "school", + "science", + "scoop", + "scrub", + "scuba", + "seasons", + "second", + "sedan", + "seeded", + "segments", + "seismic", + "selfish", + "semifinal", + "sensible", + "september", + "sequence", + "serving", + "session", + "setup", + "seventh", + "sewage", + "shackles", + "shelter", + "shipped", + "shocking", + "shrugged", + "shuffled", + "shyness", + "siblings", + "sickness", + "sidekick", + "sieve", + "sifting", + "sighting", + "silk", + "simplest", + "sincerely", + "sipped", + "siren", + "situated", + "sixteen", + "sizes", + "skater", + "skew", + "skirting", + "skulls", + "skydive", + "slackens", + "sleepless", + "slid", + "slower", + "slug", + "smash", + "smelting", + "smidgen", + "smog", + "smuggled", + "snake", + "sneeze", + "sniff", + "snout", + "snug", + "soapy", + "sober", + "soccer", + "soda", + "software", + "soggy", + "soil", + "solved", + "somewhere", + "sonic", + "soothe", + "soprano", + "sorry", + "southern", + "sovereign", + "sowed", + "soya", + "space", + "speedy", + "sphere", + "spiders", + "splendid", + "spout", + "sprig", + "spud", + "spying", + "square", + "stacking", + "stellar", + "stick", + "stockpile", + "strained", + "stunning", + "stylishly", + "subtly", + "succeed", + "suddenly", + "suede", + "suffice", + "sugar", + "suitcase", + "sulking", + "summon", + "sunken", + "superior", + "surfer", + "sushi", + "suture", + "swagger", + "swept", + "swiftly", + "sword", + "swung", + "syllabus", + "symptoms", + "syndrome", + "syringe", + "system", + "taboo", + "tacit", + "tadpoles", + "tagged", + "tail", + "taken", + "talent", + "tamper", + "tanks", + "tapestry", + "tarnished", + "tasked", + "tattoo", + "taunts", + "tavern", + "tawny", + "taxi", + "teardrop", + "technical", + "tedious", + "teeming", + "tell", + "template", + "tender", + "tepid", + "tequila", + "terminal", + "testing", + "tether", + "textbook", + "thaw", + "theatrics", + "thirsty", + "thorn", + "threaten", + "thumbs", + "thwart", + "ticket", + "tidy", + "tiers", + "tiger", + "tilt", + "timber", + "tinted", + "tipsy", + "tirade", + "tissue", + "titans", + "toaster", + "tobacco", + "today", + "toenail", + "toffee", + "together", + "toilet", + "token", + "tolerant", + "tomorrow", + "tonic", + "toolbox", + "topic", + "torch", + "tossed", + "total", + "touchy", + "towel", + "toxic", + "toyed", + "trash", + "trendy", + "tribal", + "trolling", + "truth", + "trying", + "tsunami", + "tubes", + "tucks", + "tudor", + "tuesday", + "tufts", + "tugs", + "tuition", + "tulips", + "tumbling", + "tunnel", + "turnip", + "tusks", + "tutor", + "tuxedo", + "twang", + "tweezers", + "twice", + "twofold", + "tycoon", + "typist", + "tyrant", + "ugly", + "ulcers", + "ultimate", + "umbrella", + "umpire", + "unafraid", + "unbending", + "uncle", + "under", + "uneven", + "unfit", + "ungainly", + "unhappy", + "union", + "unjustly", + "unknown", + "unlikely", + "unmask", + "unnoticed", + "unopened", + "unplugs", + "unquoted", + "unrest", + "unsafe", + "until", + "unusual", + "unveil", + "unwind", + "unzip", + "upbeat", + "upcoming", + "update", + "upgrade", + "uphill", + "upkeep", + "upload", + "upon", + "upper", + "upright", + "upstairs", + "uptight", + "upwards", + "urban", + "urchins", + "urgent", + "usage", + "useful", + "usher", + "using", + "usual", + "utensils", + "utility", + "utmost", + "utopia", + "uttered", + "vacation", + "vague", + "vain", + "value", + "vampire", + "vane", + "vapidly", + "vary", + "vastness", + "vats", + "vaults", + "vector", + "veered", + "vegan", + "vehicle", + "vein", + "velvet", + "venomous", + "verification", + "vessel", + "veteran", + "vexed", + "vials", + "vibrate", + "victim", + "video", + "viewpoint", + "vigilant", + "viking", + "village", + "vinegar", + "violin", + "vipers", + "virtual", + "visited", + "vitals", + "vivid", + "vixen", + "vocal", + "vogue", + "voice", + "volcano", + "vortex", + "voted", + "voucher", + "vowels", + "voyage", + "vulture", + "wade", + "waffle", + "wagtail", + "waist", + "waking", + "wallets", + "wanted", + "warped", + "washing", + "water", + "waveform", + "waxing", + "wayside", + "weavers", + "website", + "wedge", + "weekday", + "weird", + "welders", + "went", + "wept", + "were", + "western", + "wetsuit", + "whale", + "when", + "whipped", + "whole", + "wickets", + "width", + "wield", + "wife", + "wiggle", + "wildly", + "winter", + "wipeout", + "wiring", + "wise", + "withdrawn", + "wives", + "wizard", + "wobbly", + "woes", + "woken", + "wolf", + "womanly", + "wonders", + "woozy", + "worry", + "wounded", + "woven", + "wrap", + "wrist", + "wrong", + "yacht", + "yahoo", + "yanks", + "yard", + "yawning", + "yearbook", + "yellow", + "yesterday", + "yeti", + "yields", + "yodel", + "yoga", + "younger", + "yoyo", + "zapped", + "zeal", + "zebra", + "zero", + "zesty", + "zigzags", + "zinger", + "zippers", + "zodiac", + "zombie", + "zones", + "zoom" + }), 3) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/english_old.h b/src/Mnemonics/english_old.h new file mode 100644 index 0000000..d184107 --- /dev/null +++ b/src/Mnemonics/english_old.h @@ -0,0 +1,1688 @@ +// Word list originally created as part of the Electrum project, Copyright (C) 2014 Thomas Voegtlin +// +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file english_old.h + * + * \brief Older version of English word list and map. + */ + +#ifndef ENGLISH_OLD_H +#define ENGLISH_OLD_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class EnglishOld: public Base + { + public: + EnglishOld(): Base("EnglishOld", std::vector({ + "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" + }), 4) + { + populate_maps(ALLOW_DUPLICATE_PREFIXES | ALLOW_SHORT_WORDS); + } + }; +} + +#endif diff --git a/src/Mnemonics/esperanto.h b/src/Mnemonics/esperanto.h new file mode 100644 index 0000000..7789aaa --- /dev/null +++ b/src/Mnemonics/esperanto.h @@ -0,0 +1,1695 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file esperanto.h + * + * \brief New Esperanto word list and map. + */ + +/* + * Word list authored by: dnaleor, Engelberg, ProkhorZ + * Sources: + * Baza Radikaro Oficiala + * Reta Vortaro (http://www.reta-vortaro.de/revo/) + * Esperanto Panorama - Esperanto-English Dictionary (http://www.esperanto-panorama.net/vortaro/eoen.htm) + * ESPDIC - Paul Denisowski (http://www.denisowski.org/Esperanto/ESPDIC/espdic.txt) + */ + +#ifndef ESPERANTO_H +#define ESPERANTO_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Esperanto: public Base + { + public: + Esperanto(): Base("Esperanto", std::vector({ + "abako", + "abdiki", + "abelo", + "abituriento", + "ablativo", + "abnorma", + "abonantoj", + "abrikoto", + "absoluta", + "abunda", + "acetono", + "acida", + "adapti", + "adekvata", + "adheri", + "adicii", + "adjektivo", + "administri", + "adolesko", + "adreso", + "adstringa", + "adulto", + "advokato", + "adzo", + "aeroplano", + "aferulo", + "afgana", + "afiksi", + "aflaba", + "aforismo", + "afranki", + "aftozo", + "afusto", + "agavo", + "agento", + "agiti", + "aglo", + "agmaniero", + "agnoski", + "agordo", + "agrabla", + "agtipo", + "agutio", + "aikido", + "ailanto", + "aina", + "ajatolo", + "ajgenvaloro", + "ajlobulbo", + "ajnlitera", + "ajuto", + "ajzi", + "akademio", + "akcepti", + "akeo", + "akiri", + "aklamado", + "akmeo", + "akno", + "akompani", + "akrobato", + "akselo", + "aktiva", + "akurata", + "akvofalo", + "alarmo", + "albumo", + "alcedo", + "aldoni", + "aleo", + "alfabeto", + "algo", + "alhasti", + "aligatoro", + "alkoholo", + "almozo", + "alnomo", + "alojo", + "alpinisto", + "alrigardi", + "alskribi", + "alta", + "alumeto", + "alveni", + "alzaca", + "amaso", + "ambasado", + "amdeklaro", + "amebo", + "amfibio", + "amhara", + "amiko", + "amkanto", + "amletero", + "amnestio", + "amoranto", + "amplekso", + "amrakonto", + "amsterdama", + "amuzi", + "ananaso", + "androido", + "anekdoto", + "anfrakto", + "angulo", + "anheli", + "animo", + "anjono", + "ankro", + "anonci", + "anpriskribo", + "ansero", + "antikva", + "anuitato", + "aorto", + "aparta", + "aperti", + "apika", + "aplikado", + "apneo", + "apogi", + "aprobi", + "apsido", + "apterigo", + "apudesto", + "araneo", + "arbo", + "ardeco", + "aresti", + "argilo", + "aristokrato", + "arko", + "arlekeno", + "armi", + "arniko", + "aromo", + "arpio", + "arsenalo", + "artisto", + "aruba", + "arvorto", + "asaio", + "asbesto", + "ascendi", + "asekuri", + "asfalto", + "asisti", + "askalono", + "asocio", + "aspekti", + "astro", + "asulo", + "atakonto", + "atendi", + "atingi", + "atleto", + "atmosfero", + "atomo", + "atropino", + "atuto", + "avataro", + "aventuro", + "aviadilo", + "avokado", + "azaleo", + "azbuko", + "azenino", + "azilpetanto", + "azoto", + "azteka", + "babili", + "bacilo", + "badmintono", + "bagatelo", + "bahama", + "bajoneto", + "baki", + "balai", + "bambuo", + "bani", + "baobabo", + "bapti", + "baro", + "bastono", + "batilo", + "bavara", + "bazalto", + "beata", + "bebofono", + "bedo", + "begonio", + "behaviorismo", + "bejlo", + "bekero", + "belarto", + "bemolo", + "benko", + "bereto", + "besto", + "betulo", + "bevelo", + "bezoni", + "biaso", + "biblioteko", + "biciklo", + "bidaro", + "bieno", + "bifsteko", + "bigamiulo", + "bijekcio", + "bikino", + "bildo", + "bimetalismo", + "bindi", + "biografio", + "birdo", + "biskvito", + "bitlibro", + "bivako", + "bizara", + "bjalistoka", + "blanka", + "bleki", + "blinda", + "blovi", + "blua", + "boato", + "bobsledo", + "bocvanano", + "bodisatvo", + "bofratino", + "bogefratoj", + "bohema", + "boji", + "bokalo", + "boli", + "bombono", + "bona", + "bopatrino", + "bordo", + "bosko", + "botelo", + "bovido", + "brakpleno", + "bretaro", + "brikmuro", + "broso", + "brulema", + "bubalo", + "buctrapi", + "budo", + "bufedo", + "bugio", + "bujabeso", + "buklo", + "buldozo", + "bumerango", + "bunta", + "burokrataro", + "busbileto", + "butero", + "buzuko", + "caro", + "cebo", + "ceceo", + "cedro", + "cefalo", + "cejana", + "cekumo", + "celebri", + "cemento", + "cent", + "cepo", + "certa", + "cetera", + "cezio", + "ciano", + "cibeto", + "cico", + "cidro", + "cifero", + "cigaredo", + "ciklo", + "cilindro", + "cimbalo", + "cinamo", + "cipreso", + "cirkonstanco", + "cisterno", + "citrono", + "ciumi", + "civilizado", + "colo", + "congo", + "cunamo", + "cvana", + "dabi", + "daco", + "dadaismo", + "dafodilo", + "dago", + "daimio", + "dajmono", + "daktilo", + "dalio", + "damo", + "danki", + "darmo", + "datumoj", + "dazipo", + "deadmoni", + "debeto", + "decidi", + "dedukti", + "deerigi", + "defendi", + "degeli", + "dehaki", + "deirpunkto", + "deklaracio", + "delikata", + "demandi", + "dento", + "dependi", + "derivi", + "desegni", + "detrui", + "devi", + "deziri", + "dialogo", + "dicentro", + "didaktika", + "dieto", + "diferenci", + "digesti", + "diino", + "dikfingro", + "diligenta", + "dimensio", + "dinamo", + "diodo", + "diplomo", + "direkte", + "diskuti", + "diurno", + "diversa", + "dizajno", + "dobrogitaro", + "docento", + "dogano", + "dojeno", + "doktoro", + "dolori", + "domego", + "donaci", + "dopado", + "dormi", + "dosierujo", + "dotita", + "dozeno", + "drato", + "dresi", + "drinki", + "droni", + "druido", + "duaranga", + "dubi", + "ducent", + "dudek", + "duelo", + "dufoje", + "dugongo", + "duhufa", + "duilo", + "dujare", + "dukato", + "duloka", + "dumtempe", + "dungi", + "duobla", + "dupiedulo", + "dura", + "dusenca", + "dutaga", + "duuma", + "duvalvuloj", + "duzo", + "ebena", + "eblecoj", + "ebono", + "ebria", + "eburo", + "ecaro", + "ecigi", + "ecoj", + "edelvejso", + "editoro", + "edro", + "eduki", + "edzino", + "efektiva", + "efiki", + "efloreski", + "egala", + "egeco", + "egiptologo", + "eglefino", + "egoista", + "egreto", + "ejakuli", + "ejlo", + "ekarto", + "ekbruligi", + "ekceli", + "ekde", + "ekesti", + "ekfirmao", + "ekgliti", + "ekhavi", + "ekipi", + "ekkapti", + "eklezio", + "ekmalsati", + "ekonomio", + "ekpluvi", + "ekrano", + "ekster", + "ektiri", + "ekumeno", + "ekvilibro", + "ekzemplo", + "elasta", + "elbalai", + "elcento", + "eldoni", + "elektro", + "elfari", + "elgliti", + "elhaki", + "elipso", + "elkovi", + "ellasi", + "elmeti", + "elnutri", + "elokventa", + "elparoli", + "elrevigi", + "elstari", + "elteni", + "eluzita", + "elvoki", + "elzasa", + "emajlo", + "embaraso", + "emerito", + "emfazo", + "eminenta", + "emocio", + "empiria", + "emulsio", + "enarkivigi", + "enboteligi", + "enciklopedio", + "endorfino", + "energio", + "enfermi", + "engluti", + "enhavo", + "enigmo", + "enjekcio", + "enketi", + "enlanda", + "enmeti", + "enorma", + "enplanti", + "enradiki", + "enspezo", + "entrepreni", + "enui", + "envolvi", + "enzimo", + "eono", + "eosto", + "epitafo", + "epoko", + "epriskribebla", + "epsilono", + "erari", + "erbio", + "erco", + "erekti", + "ergonomia", + "erikejo", + "ermito", + "erotika", + "erpilo", + "erupcio", + "esameno", + "escepti", + "esenco", + "eskapi", + "esotera", + "esperi", + "estonto", + "etapo", + "etendi", + "etfingro", + "etikedo", + "etlitero", + "etmakleristo", + "etnika", + "etoso", + "etradio", + "etskala", + "etullernejo", + "evakui", + "evento", + "eviti", + "evolui", + "ezoko", + "fabriko", + "facila", + "fadeno", + "fagoto", + "fajro", + "fakto", + "fali", + "familio", + "fanatiko", + "farbo", + "fasko", + "fatala", + "favora", + "fazeolo", + "febro", + "federacio", + "feino", + "fekunda", + "felo", + "femuro", + "fenestro", + "fermi", + "festi", + "fetora", + "fezo", + "fiasko", + "fibro", + "fidela", + "fiera", + "fifama", + "figuro", + "fiherbo", + "fiinsekto", + "fiksa", + "filmo", + "fimensa", + "finalo", + "fiolo", + "fiparoli", + "firmao", + "fisko", + "fitingo", + "fiuzanto", + "fivorto", + "fiziko", + "fjordo", + "flago", + "flegi", + "flirti", + "floro", + "flugi", + "fobio", + "foceno", + "foirejo", + "fojfoje", + "fokuso", + "folio", + "fomenti", + "fonto", + "formulo", + "fosforo", + "fotografi", + "fratino", + "fremda", + "friti", + "frosto", + "frua", + "ftizo", + "fuelo", + "fugo", + "fuksia", + "fulmilo", + "fumanto", + "fundamento", + "fuorto", + "furioza", + "fusilo", + "futbalo", + "fuzio", + "gabardino", + "gado", + "gaela", + "gafo", + "gagato", + "gaja", + "gaki", + "galanta", + "gamao", + "ganto", + "gapulo", + "gardi", + "gasto", + "gavio", + "gazeto", + "geamantoj", + "gebani", + "geedzeco", + "gefratoj", + "geheno", + "gejsero", + "geko", + "gelateno", + "gemisto", + "geniulo", + "geografio", + "gepardo", + "geranio", + "gestolingvo", + "geto", + "geumo", + "gibono", + "giganta", + "gildo", + "gimnastiko", + "ginekologo", + "gipsi", + "girlando", + "gistfungo", + "gitaro", + "glazuro", + "glebo", + "gliti", + "globo", + "gluti", + "gnafalio", + "gnejso", + "gnomo", + "gnuo", + "gobio", + "godetio", + "goeleto", + "gojo", + "golfludejo", + "gombo", + "gondolo", + "gorilo", + "gospelo", + "gotika", + "granda", + "greno", + "griza", + "groto", + "grupo", + "guano", + "gubernatoro", + "gudrotuko", + "gufo", + "gujavo", + "guldeno", + "gumi", + "gupio", + "guruo", + "gusto", + "guto", + "guvernistino", + "gvardio", + "gverilo", + "gvidanto", + "habitato", + "hadito", + "hafnio", + "hagiografio", + "haitiano", + "hajlo", + "hakbloko", + "halti", + "hamstro", + "hangaro", + "hapalo", + "haro", + "hasta", + "hati", + "havebla", + "hazardo", + "hebrea", + "hedero", + "hegemonio", + "hejmo", + "hektaro", + "helpi", + "hemisfero", + "heni", + "hepato", + "herbo", + "hesa", + "heterogena", + "heziti", + "hiacinto", + "hibrida", + "hidrogeno", + "hieroglifo", + "higieno", + "hihii", + "hilumo", + "himno", + "hindino", + "hiperteksto", + "hirundo", + "historio", + "hobio", + "hojli", + "hokeo", + "hologramo", + "homido", + "honesta", + "hopi", + "horizonto", + "hospitalo", + "hotelo", + "huadi", + "hubo", + "hufumo", + "hugenoto", + "hukero", + "huligano", + "humana", + "hundo", + "huoj", + "hupilo", + "hurai", + "husaro", + "hutuo", + "huzo", + "iafoje", + "iagrade", + "iamaniere", + "iarelate", + "iaspeca", + "ibekso", + "ibiso", + "idaro", + "ideala", + "idiomo", + "idolo", + "iele", + "igluo", + "ignori", + "iguamo", + "igvano", + "ikono", + "iksodo", + "ikto", + "iliaflanke", + "ilkomputilo", + "ilobreto", + "ilremedo", + "ilumini", + "imagi", + "imitado", + "imperio", + "imuna", + "incidento", + "industrio", + "inerta", + "infano", + "ingenra", + "inhali", + "iniciati", + "injekti", + "inklino", + "inokuli", + "insekto", + "inteligenta", + "inundi", + "inviti", + "ioma", + "ionosfero", + "iperito", + "ipomeo", + "irana", + "irejo", + "irigacio", + "ironio", + "isato", + "islamo", + "istempo", + "itinero", + "itrio", + "iuloke", + "iumaniere", + "iutempe", + "izolita", + "jado", + "jaguaro", + "jakto", + "jama", + "januaro", + "japano", + "jarringo", + "jazo", + "jenoj", + "jesulo", + "jetavio", + "jezuito", + "jodli", + "joviala", + "juano", + "jubileo", + "judismo", + "jufto", + "juki", + "julio", + "juneca", + "jupo", + "juristo", + "juste", + "juvelo", + "kabineto", + "kadrato", + "kafo", + "kahelo", + "kajako", + "kakao", + "kalkuli", + "kampo", + "kanti", + "kapitalo", + "karaktero", + "kaserolo", + "katapulto", + "kaverna", + "kazino", + "kebabo", + "kefiro", + "keglo", + "kejlo", + "kekso", + "kelka", + "kemio", + "kerno", + "kesto", + "kiamaniere", + "kibuco", + "kidnapi", + "kielo", + "kikero", + "kilogramo", + "kimono", + "kinejo", + "kiosko", + "kirurgo", + "kisi", + "kitelo", + "kivio", + "klavaro", + "klerulo", + "klini", + "klopodi", + "klubo", + "knabo", + "knedi", + "koalo", + "kobalto", + "kodigi", + "kofro", + "kohera", + "koincidi", + "kojoto", + "kokoso", + "koloro", + "komenci", + "kontrakto", + "kopio", + "korekte", + "kosti", + "kotono", + "kovri", + "krajono", + "kredi", + "krii", + "krom", + "kruco", + "ksantino", + "ksenono", + "ksilofono", + "ksosa", + "kubuto", + "kudri", + "kuglo", + "kuiri", + "kuko", + "kulero", + "kumuluso", + "kuneco", + "kupro", + "kuri", + "kuseno", + "kutimo", + "kuvo", + "kuzino", + "kvalito", + "kverko", + "kvin", + "kvoto", + "labori", + "laculo", + "ladbotelo", + "lafo", + "laguno", + "laikino", + "laktobovino", + "lampolumo", + "landkarto", + "laosa", + "lapono", + "larmoguto", + "lastjare", + "latitudo", + "lavejo", + "lazanjo", + "leciono", + "ledosako", + "leganto", + "lekcio", + "lemura", + "lentuga", + "leopardo", + "leporo", + "lerni", + "lesivo", + "letero", + "levilo", + "lezi", + "liano", + "libera", + "liceo", + "lieno", + "lifto", + "ligilo", + "likvoro", + "lila", + "limono", + "lingvo", + "lipo", + "lirika", + "listo", + "literatura", + "liveri", + "lobio", + "logika", + "lojala", + "lokalo", + "longa", + "lordo", + "lotado", + "loza", + "luanto", + "lubriki", + "lucida", + "ludema", + "luigi", + "lukso", + "luli", + "lumbilda", + "lunde", + "lupago", + "lustro", + "lutilo", + "luzerno", + "maato", + "maceri", + "madono", + "mafiano", + "magazeno", + "mahometano", + "maizo", + "majstro", + "maketo", + "malgranda", + "mamo", + "mandareno", + "maorio", + "mapigi", + "marini", + "masko", + "mateno", + "mazuto", + "meandro", + "meblo", + "mecenato", + "medialo", + "mefito", + "megafono", + "mejlo", + "mekanika", + "melodia", + "membro", + "mendi", + "mergi", + "mespilo", + "metoda", + "mevo", + "mezuri", + "miaflanke", + "micelio", + "mielo", + "migdalo", + "mikrofilmo", + "militi", + "mimiko", + "mineralo", + "miopa", + "miri", + "mistera", + "mitralo", + "mizeri", + "mjelo", + "mnemoniko", + "mobilizi", + "mocio", + "moderna", + "mohajro", + "mokadi", + "molaro", + "momento", + "monero", + "mopso", + "mordi", + "moskito", + "motoro", + "movimento", + "mozaiko", + "mueli", + "mukozo", + "muldi", + "mumio", + "munti", + "muro", + "muskolo", + "mutacio", + "muzikisto", + "nabo", + "nacio", + "nadlo", + "nafto", + "naiva", + "najbaro", + "nanometro", + "napo", + "narciso", + "naski", + "naturo", + "navigi", + "naztruo", + "neatendite", + "nebulo", + "necesa", + "nedankinde", + "neebla", + "nefari", + "negoco", + "nehavi", + "neimagebla", + "nektaro", + "nelonga", + "nematura", + "nenia", + "neordinara", + "nepra", + "nervuro", + "nesto", + "nete", + "neulo", + "nevino", + "nifo", + "nigra", + "nihilisto", + "nikotino", + "nilono", + "nimfeo", + "nitrogeno", + "nivelo", + "nobla", + "nocio", + "nodozo", + "nokto", + "nomkarto", + "norda", + "nostalgio", + "notbloko", + "novico", + "nuanco", + "nuboza", + "nuda", + "nugato", + "nuklea", + "nuligi", + "numero", + "nuntempe", + "nupto", + "nura", + "nutri", + "oazo", + "obei", + "objekto", + "oblikva", + "obolo", + "observi", + "obtuza", + "obuso", + "oceano", + "odekolono", + "odori", + "oferti", + "oficiala", + "ofsajdo", + "ofte", + "ogivo", + "ogro", + "ojstredoj", + "okaze", + "okcidenta", + "okro", + "oksido", + "oktobro", + "okulo", + "oldulo", + "oleo", + "olivo", + "omaro", + "ombro", + "omego", + "omikrono", + "omleto", + "omnibuso", + "onagro", + "ondo", + "oneco", + "onidire", + "onklino", + "onlajna", + "onomatopeo", + "ontologio", + "opaka", + "operacii", + "opinii", + "oportuna", + "opresi", + "optimisto", + "oratoro", + "orbito", + "ordinara", + "orelo", + "orfino", + "organizi", + "orienta", + "orkestro", + "orlo", + "orminejo", + "ornami", + "ortangulo", + "orumi", + "oscedi", + "osmozo", + "ostocerbo", + "ovalo", + "ovingo", + "ovoblanko", + "ovri", + "ovulado", + "ozono", + "pacama", + "padeli", + "pafilo", + "pagigi", + "pajlo", + "paketo", + "palaco", + "pampelmo", + "pantalono", + "papero", + "paroli", + "pasejo", + "patro", + "pavimo", + "peco", + "pedalo", + "peklita", + "pelikano", + "pensiono", + "peplomo", + "pesilo", + "petanto", + "pezoforto", + "piano", + "picejo", + "piede", + "pigmento", + "pikema", + "pilkoludo", + "pimento", + "pinglo", + "pioniro", + "pipromento", + "pirato", + "pistolo", + "pitoreska", + "piulo", + "pivoti", + "pizango", + "planko", + "plektita", + "plibonigi", + "ploradi", + "plurlingva", + "pobo", + "podio", + "poeto", + "pogranda", + "pohora", + "pokalo", + "politekniko", + "pomarbo", + "ponevosto", + "populara", + "porcelana", + "postkompreno", + "poteto", + "poviga", + "pozitiva", + "prapatroj", + "precize", + "pridemandi", + "probable", + "pruntanto", + "psalmo", + "psikologio", + "psoriazo", + "pterido", + "publiko", + "pudro", + "pufo", + "pugnobato", + "pulovero", + "pumpi", + "punkto", + "pupo", + "pureo", + "puso", + "putrema", + "puzlo", + "rabate", + "racionala", + "radiko", + "rafinado", + "raguo", + "rajto", + "rakonti", + "ralio", + "rampi", + "rando", + "rapida", + "rastruma", + "ratifiki", + "raviolo", + "razeno", + "reakcio", + "rebildo", + "recepto", + "redakti", + "reenigi", + "reformi", + "regiono", + "rehavi", + "reinspekti", + "rejesi", + "reklamo", + "relativa", + "rememori", + "renkonti", + "reorganizado", + "reprezenti", + "respondi", + "retumilo", + "reuzebla", + "revidi", + "rezulti", + "rialo", + "ribeli", + "ricevi", + "ridiga", + "rifuginto", + "rigardi", + "rikolti", + "rilati", + "rimarki", + "rinocero", + "ripozi", + "riski", + "ritmo", + "rivero", + "rizokampo", + "roboto", + "rododendro", + "rojo", + "rokmuziko", + "rolvorto", + "romantika", + "ronroni", + "rosino", + "rotondo", + "rovero", + "rozeto", + "rubando", + "rudimenta", + "rufa", + "rugbeo", + "ruino", + "ruleto", + "rumoro", + "runo", + "rupio", + "rura", + "rustimuna", + "ruzulo", + "sabato", + "sadismo", + "safario", + "sagaca", + "sakfluto", + "salti", + "samtage", + "sandalo", + "sapejo", + "sarongo", + "satelito", + "savano", + "sbiro", + "sciado", + "seanco", + "sebo", + "sedativo", + "segligno", + "sekretario", + "selektiva", + "semajno", + "senpeza", + "separeo", + "servilo", + "sesangulo", + "setli", + "seurigi", + "severa", + "sezono", + "sfagno", + "sfero", + "sfinkso", + "siatempe", + "siblado", + "sidejo", + "siesto", + "sifono", + "signalo", + "siklo", + "silenti", + "simpla", + "sinjoro", + "siropo", + "sistemo", + "situacio", + "siverto", + "sizifa", + "skatolo", + "skemo", + "skianto", + "sklavo", + "skorpio", + "skribisto", + "skulpti", + "skvamo", + "slango", + "sledeto", + "sliparo", + "smeraldo", + "smirgi", + "smokingo", + "smuto", + "snoba", + "snufegi", + "sobra", + "sociano", + "sodakvo", + "sofo", + "soifi", + "sojlo", + "soklo", + "soldato", + "somero", + "sonilo", + "sopiri", + "sorto", + "soulo", + "soveto", + "sparkado", + "speciala", + "spiri", + "splito", + "sporto", + "sprita", + "spuro", + "stabila", + "stelfiguro", + "stimulo", + "stomako", + "strato", + "studanto", + "subgrupo", + "suden", + "suferanta", + "sugesti", + "suito", + "sukero", + "sulko", + "sume", + "sunlumo", + "super", + "surskribeto", + "suspekti", + "suturo", + "svati", + "svenfali", + "svingi", + "svopo", + "tabako", + "taglumo", + "tajloro", + "taksimetro", + "talento", + "tamen", + "tanko", + "taoismo", + "tapioko", + "tarifo", + "tasko", + "tatui", + "taverno", + "teatro", + "tedlaboro", + "tegmento", + "tehoro", + "teknika", + "telefono", + "tempo", + "tenisejo", + "teorie", + "teraso", + "testudo", + "tetablo", + "teujo", + "tezo", + "tialo", + "tibio", + "tielnomata", + "tifono", + "tigro", + "tikli", + "timida", + "tinkturo", + "tiom", + "tiparo", + "tirkesto", + "titolo", + "tiutempe", + "tizano", + "tobogano", + "tofeo", + "togo", + "toksa", + "tolerema", + "tombolo", + "tondri", + "topografio", + "tordeti", + "tosti", + "totalo", + "traduko", + "tredi", + "triangulo", + "tropika", + "trumpeto", + "tualeto", + "tubisto", + "tufgrebo", + "tuja", + "tukano", + "tulipo", + "tumulto", + "tunelo", + "turisto", + "tusi", + "tutmonda", + "tvisto", + "udono", + "uesto", + "ukazo", + "ukelelo", + "ulcero", + "ulmo", + "ultimato", + "ululi", + "umbiliko", + "unco", + "ungego", + "uniformo", + "unkti", + "unukolora", + "uragano", + "urbano", + "uretro", + "urino", + "ursido", + "uskleco", + "usonigi", + "utero", + "utila", + "utopia", + "uverturo", + "uzadi", + "uzeblo", + "uzino", + "uzkutimo", + "uzofini", + "uzurpi", + "uzvaloro", + "vadejo", + "vafleto", + "vagono", + "vahabismo", + "vajco", + "vakcino", + "valoro", + "vampiro", + "vangharoj", + "vaporo", + "varma", + "vasta", + "vato", + "vazaro", + "veaspekta", + "vedismo", + "vegetalo", + "vehiklo", + "vejno", + "vekita", + "velstango", + "vemieno", + "vendi", + "vepro", + "verando", + "vespero", + "veturi", + "veziko", + "viando", + "vibri", + "vico", + "videbla", + "vifio", + "vigla", + "viktimo", + "vila", + "vimeno", + "vintro", + "violo", + "vippuno", + "virtuala", + "viskoza", + "vitro", + "viveca", + "viziti", + "vobli", + "vodko", + "vojeto", + "vokegi", + "volbo", + "vomema", + "vono", + "vortaro", + "vosto", + "voti", + "vrako", + "vringi", + "vualo", + "vulkano", + "vundo", + "vuvuzelo", + "zamenhofa", + "zapi", + "zebro", + "zefiro", + "zeloto", + "zenismo", + "zeolito", + "zepelino", + "zeto", + "zigzagi", + "zinko", + "zipo", + "zirkonio", + "zodiako", + "zoeto", + "zombio", + "zono", + "zoologio", + "zorgi", + "zukino", + "zumilo", + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/french.h b/src/Mnemonics/french.h new file mode 100644 index 0000000..a472263 --- /dev/null +++ b/src/Mnemonics/french.h @@ -0,0 +1,1686 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file french.h + * + * \brief French word list and map. + */ + +#ifndef FRENCH_H +#define FRENCH_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class French: public Base + { + public: + French(): Base("Français", std::vector({ + "abandon", + "abattre", + "aboi", + "abolir", + "aborder", + "abri", + "absence", + "absolu", + "abuser", + "acacia", + "acajou", + "accent", + "accord", + "accrocher", + "accuser", + "acerbe", + "achat", + "acheter", + "acide", + "acier", + "acquis", + "acte", + "action", + "adage", + "adepte", + "adieu", + "admettre", + "admis", + "adorer", + "adresser", + "aduler", + "affaire", + "affirmer", + "afin", + "agacer", + "agent", + "agir", + "agiter", + "agonie", + "agrafe", + "agrume", + "aider", + "aigle", + "aigre", + "aile", + "ailleurs", + "aimant", + "aimer", + "ainsi", + "aise", + "ajouter", + "alarme", + "album", + "alcool", + "alerte", + "algue", + "alibi", + "aller", + "allumer", + "alors", + "amande", + "amener", + "amie", + "amorcer", + "amour", + "ample", + "amuser", + "ananas", + "ancien", + "anglais", + "angoisse", + "animal", + "anneau", + "annoncer", + "apercevoir", + "apparence", + "appel", + "apporter", + "apprendre", + "appuyer", + "arbre", + "arcade", + "arceau", + "arche", + "ardeur", + "argent", + "argile", + "aride", + "arme", + "armure", + "arracher", + "arriver", + "article", + "asile", + "aspect", + "assaut", + "assez", + "assister", + "assurer", + "astre", + "astuce", + "atlas", + "atroce", + "attacher", + "attente", + "attirer", + "aube", + "aucun", + "audace", + "auparavant", + "auquel", + "aurore", + "aussi", + "autant", + "auteur", + "autoroute", + "autre", + "aval", + "avant", + "avec", + "avenir", + "averse", + "aveu", + "avide", + "avion", + "avis", + "avoir", + "avouer", + "avril", + "azote", + "azur", + "badge", + "bagage", + "bague", + "bain", + "baisser", + "balai", + "balcon", + "balise", + "balle", + "bambou", + "banane", + "banc", + "bandage", + "banjo", + "banlieue", + "bannir", + "banque", + "baobab", + "barbe", + "barque", + "barrer", + "bassine", + "bataille", + "bateau", + "battre", + "baver", + "bavoir", + "bazar", + "beau", + "beige", + "berger", + "besoin", + "beurre", + "biais", + "biceps", + "bidule", + "bien", + "bijou", + "bilan", + "billet", + "blanc", + "blason", + "bleu", + "bloc", + "blond", + "bocal", + "boire", + "boiserie", + "boiter", + "bonbon", + "bondir", + "bonheur", + "bordure", + "borgne", + "borner", + "bosse", + "bouche", + "bouder", + "bouger", + "boule", + "bourse", + "bout", + "boxe", + "brader", + "braise", + "branche", + "braquer", + "bras", + "brave", + "brebis", + "brevet", + "brider", + "briller", + "brin", + "brique", + "briser", + "broche", + "broder", + "bronze", + "brosser", + "brouter", + "bruit", + "brute", + "budget", + "buffet", + "bulle", + "bureau", + "buriner", + "buste", + "buter", + "butiner", + "cabas", + "cabinet", + "cabri", + "cacao", + "cacher", + "cadeau", + "cadre", + "cage", + "caisse", + "caler", + "calme", + "camarade", + "camion", + "campagne", + "canal", + "canif", + "capable", + "capot", + "carat", + "caresser", + "carie", + "carpe", + "cartel", + "casier", + "casque", + "casserole", + "cause", + "cavale", + "cave", + "ceci", + "cela", + "celui", + "cendre", + "cent", + "cependant", + "cercle", + "cerise", + "cerner", + "certes", + "cerveau", + "cesser", + "chacun", + "chair", + "chaleur", + "chamois", + "chanson", + "chaque", + "charge", + "chasse", + "chat", + "chaud", + "chef", + "chemin", + "cheveu", + "chez", + "chicane", + "chien", + "chiffre", + "chiner", + "chiot", + "chlore", + "choc", + "choix", + "chose", + "chou", + "chute", + "cibler", + "cidre", + "ciel", + "cigale", + "cinq", + "cintre", + "cirage", + "cirque", + "ciseau", + "citation", + "citer", + "citron", + "civet", + "clairon", + "clan", + "classe", + "clavier", + "clef", + "climat", + "cloche", + "cloner", + "clore", + "clos", + "clou", + "club", + "cobra", + "cocon", + "coiffer", + "coin", + "colline", + "colon", + "combat", + "comme", + "compte", + "conclure", + "conduire", + "confier", + "connu", + "conseil", + "contre", + "convenir", + "copier", + "cordial", + "cornet", + "corps", + "cosmos", + "coton", + "couche", + "coude", + "couler", + "coupure", + "cour", + "couteau", + "couvrir", + "crabe", + "crainte", + "crampe", + "cran", + "creuser", + "crever", + "crier", + "crime", + "crin", + "crise", + "crochet", + "croix", + "cruel", + "cuisine", + "cuite", + "culot", + "culte", + "cumul", + "cure", + "curieux", + "cuve", + "dame", + "danger", + "dans", + "davantage", + "debout", + "dedans", + "dehors", + "delta", + "demain", + "demeurer", + "demi", + "dense", + "dent", + "depuis", + "dernier", + "descendre", + "dessus", + "destin", + "dette", + "deuil", + "deux", + "devant", + "devenir", + "devin", + "devoir", + "dicton", + "dieu", + "difficile", + "digestion", + "digue", + "diluer", + "dimanche", + "dinde", + "diode", + "dire", + "diriger", + "discours", + "disposer", + "distance", + "divan", + "divers", + "docile", + "docteur", + "dodu", + "dogme", + "doigt", + "dominer", + "donation", + "donjon", + "donner", + "dopage", + "dorer", + "dormir", + "doseur", + "douane", + "double", + "douche", + "douleur", + "doute", + "doux", + "douzaine", + "draguer", + "drame", + "drap", + "dresser", + "droit", + "duel", + "dune", + "duper", + "durant", + "durcir", + "durer", + "eaux", + "effacer", + "effet", + "effort", + "effrayant", + "elle", + "embrasser", + "emmener", + "emparer", + "empire", + "employer", + "emporter", + "enclos", + "encore", + "endive", + "endormir", + "endroit", + "enduit", + "enfant", + "enfermer", + "enfin", + "enfler", + "enfoncer", + "enfuir", + "engager", + "engin", + "enjeu", + "enlever", + "ennemi", + "ennui", + "ensemble", + "ensuite", + "entamer", + "entendre", + "entier", + "entourer", + "entre", + "envelopper", + "envie", + "envoyer", + "erreur", + "escalier", + "espace", + "espoir", + "esprit", + "essai", + "essor", + "essuyer", + "estimer", + "exact", + "examiner", + "excuse", + "exemple", + "exiger", + "exil", + "exister", + "exode", + "expliquer", + "exposer", + "exprimer", + "extase", + "fable", + "facette", + "facile", + "fade", + "faible", + "faim", + "faire", + "fait", + "falloir", + "famille", + "faner", + "farce", + "farine", + "fatigue", + "faucon", + "faune", + "faute", + "faux", + "faveur", + "favori", + "faxer", + "feinter", + "femme", + "fendre", + "fente", + "ferme", + "festin", + "feuille", + "feutre", + "fiable", + "fibre", + "ficher", + "fier", + "figer", + "figure", + "filet", + "fille", + "filmer", + "fils", + "filtre", + "final", + "finesse", + "finir", + "fiole", + "firme", + "fixe", + "flacon", + "flair", + "flamme", + "flan", + "flaque", + "fleur", + "flocon", + "flore", + "flot", + "flou", + "fluide", + "fluor", + "flux", + "focus", + "foin", + "foire", + "foison", + "folie", + "fonction", + "fondre", + "fonte", + "force", + "forer", + "forger", + "forme", + "fort", + "fosse", + "fouet", + "fouine", + "foule", + "four", + "foyer", + "frais", + "franc", + "frapper", + "freiner", + "frimer", + "friser", + "frite", + "froid", + "froncer", + "fruit", + "fugue", + "fuir", + "fuite", + "fumer", + "fureur", + "furieux", + "fuser", + "fusil", + "futile", + "futur", + "gagner", + "gain", + "gala", + "galet", + "galop", + "gamme", + "gant", + "garage", + "garde", + "garer", + "gauche", + "gaufre", + "gaule", + "gaver", + "gazon", + "geler", + "genou", + "genre", + "gens", + "gercer", + "germer", + "geste", + "gibier", + "gicler", + "gilet", + "girafe", + "givre", + "glace", + "glisser", + "globe", + "gloire", + "gluant", + "gober", + "golf", + "gommer", + "gorge", + "gosier", + "goutte", + "grain", + "gramme", + "grand", + "gras", + "grave", + "gredin", + "griffure", + "griller", + "gris", + "gronder", + "gros", + "grotte", + "groupe", + "grue", + "guerrier", + "guetter", + "guider", + "guise", + "habiter", + "hache", + "haie", + "haine", + "halte", + "hamac", + "hanche", + "hangar", + "hanter", + "haras", + "hareng", + "harpe", + "hasard", + "hausse", + "haut", + "havre", + "herbe", + "heure", + "hibou", + "hier", + "histoire", + "hiver", + "hochet", + "homme", + "honneur", + "honte", + "horde", + "horizon", + "hormone", + "houle", + "housse", + "hublot", + "huile", + "huit", + "humain", + "humble", + "humide", + "humour", + "hurler", + "idole", + "igloo", + "ignorer", + "illusion", + "image", + "immense", + "immobile", + "imposer", + "impression", + "incapable", + "inconnu", + "index", + "indiquer", + "infime", + "injure", + "inox", + "inspirer", + "instant", + "intention", + "intime", + "inutile", + "inventer", + "inviter", + "iode", + "iris", + "issue", + "ivre", + "jade", + "jadis", + "jamais", + "jambe", + "janvier", + "jardin", + "jauge", + "jaunisse", + "jeter", + "jeton", + "jeudi", + "jeune", + "joie", + "joindre", + "joli", + "joueur", + "journal", + "judo", + "juge", + "juillet", + "juin", + "jument", + "jungle", + "jupe", + "jupon", + "jurer", + "juron", + "jury", + "jusque", + "juste", + "kayak", + "ketchup", + "kilo", + "kiwi", + "koala", + "label", + "lacet", + "lacune", + "laine", + "laisse", + "lait", + "lame", + "lancer", + "lande", + "laque", + "lard", + "largeur", + "larme", + "larve", + "lasso", + "laver", + "lendemain", + "lentement", + "lequel", + "lettre", + "leur", + "lever", + "levure", + "liane", + "libre", + "lien", + "lier", + "lieutenant", + "ligne", + "ligoter", + "liguer", + "limace", + "limer", + "limite", + "lingot", + "lion", + "lire", + "lisser", + "litre", + "livre", + "lobe", + "local", + "logis", + "loin", + "loisir", + "long", + "loque", + "lors", + "lotus", + "louer", + "loup", + "lourd", + "louve", + "loyer", + "lubie", + "lucide", + "lueur", + "luge", + "luire", + "lundi", + "lune", + "lustre", + "lutin", + "lutte", + "luxe", + "machine", + "madame", + "magie", + "magnifique", + "magot", + "maigre", + "main", + "mairie", + "maison", + "malade", + "malheur", + "malin", + "manche", + "manger", + "manier", + "manoir", + "manquer", + "marche", + "mardi", + "marge", + "mariage", + "marquer", + "mars", + "masque", + "masse", + "matin", + "mauvais", + "meilleur", + "melon", + "membre", + "menacer", + "mener", + "mensonge", + "mentir", + "menu", + "merci", + "merlu", + "mesure", + "mettre", + "meuble", + "meunier", + "meute", + "miche", + "micro", + "midi", + "miel", + "miette", + "mieux", + "milieu", + "mille", + "mimer", + "mince", + "mineur", + "ministre", + "minute", + "mirage", + "miroir", + "miser", + "mite", + "mixte", + "mobile", + "mode", + "module", + "moins", + "mois", + "moment", + "momie", + "monde", + "monsieur", + "monter", + "moquer", + "moral", + "morceau", + "mordre", + "morose", + "morse", + "mortier", + "morue", + "motif", + "motte", + "moudre", + "moule", + "mourir", + "mousse", + "mouton", + "mouvement", + "moyen", + "muer", + "muette", + "mugir", + "muguet", + "mulot", + "multiple", + "munir", + "muret", + "muse", + "musique", + "muter", + "nacre", + "nager", + "nain", + "naissance", + "narine", + "narrer", + "naseau", + "nasse", + "nation", + "nature", + "naval", + "navet", + "naviguer", + "navrer", + "neige", + "nerf", + "nerveux", + "neuf", + "neutre", + "neuve", + "neveu", + "niche", + "nier", + "niveau", + "noble", + "noce", + "nocif", + "noir", + "nomade", + "nombre", + "nommer", + "nord", + "norme", + "notaire", + "notice", + "notre", + "nouer", + "nougat", + "nourrir", + "nous", + "nouveau", + "novice", + "noyade", + "noyer", + "nuage", + "nuance", + "nuire", + "nuit", + "nulle", + "nuque", + "oasis", + "objet", + "obliger", + "obscur", + "observer", + "obtenir", + "obus", + "occasion", + "occuper", + "ocre", + "octet", + "odeur", + "odorat", + "offense", + "officier", + "offrir", + "ogive", + "oiseau", + "olive", + "ombre", + "onctueux", + "onduler", + "ongle", + "onze", + "opter", + "option", + "orageux", + "oral", + "orange", + "orbite", + "ordinaire", + "ordre", + "oreille", + "organe", + "orgie", + "orgueil", + "orient", + "origan", + "orner", + "orteil", + "ortie", + "oser", + "osselet", + "otage", + "otarie", + "ouate", + "oublier", + "ouest", + "ours", + "outil", + "outre", + "ouvert", + "ouvrir", + "ovale", + "ozone", + "pacte", + "page", + "paille", + "pain", + "paire", + "paix", + "palace", + "palissade", + "palmier", + "palpiter", + "panda", + "panneau", + "papa", + "papier", + "paquet", + "parc", + "pardi", + "parfois", + "parler", + "parmi", + "parole", + "partir", + "parvenir", + "passer", + "pastel", + "patin", + "patron", + "paume", + "pause", + "pauvre", + "paver", + "pavot", + "payer", + "pays", + "peau", + "peigne", + "peinture", + "pelage", + "pelote", + "pencher", + "pendre", + "penser", + "pente", + "percer", + "perdu", + "perle", + "permettre", + "personne", + "perte", + "peser", + "pesticide", + "petit", + "peuple", + "peur", + "phase", + "photo", + "phrase", + "piano", + "pied", + "pierre", + "pieu", + "pile", + "pilier", + "pilote", + "pilule", + "piment", + "pincer", + "pinson", + "pinte", + "pion", + "piquer", + "pirate", + "pire", + "piste", + "piton", + "pitre", + "pivot", + "pizza", + "placer", + "plage", + "plaire", + "plan", + "plaque", + "plat", + "plein", + "pleurer", + "pliage", + "plier", + "plonger", + "plot", + "pluie", + "plume", + "plus", + "pneu", + "poche", + "podium", + "poids", + "poil", + "point", + "poire", + "poison", + "poitrine", + "poivre", + "police", + "pollen", + "pomme", + "pompier", + "poncer", + "pondre", + "pont", + "portion", + "poser", + "position", + "possible", + "poste", + "potage", + "potin", + "pouce", + "poudre", + "poulet", + "poumon", + "poupe", + "pour", + "pousser", + "poutre", + "pouvoir", + "prairie", + "premier", + "prendre", + "presque", + "preuve", + "prier", + "primeur", + "prince", + "prison", + "priver", + "prix", + "prochain", + "produire", + "profond", + "proie", + "projet", + "promener", + "prononcer", + "propre", + "prose", + "prouver", + "prune", + "public", + "puce", + "pudeur", + "puiser", + "pull", + "pulpe", + "puma", + "punir", + "purge", + "putois", + "quand", + "quartier", + "quasi", + "quatre", + "quel", + "question", + "queue", + "quiche", + "quille", + "quinze", + "quitter", + "quoi", + "rabais", + "raboter", + "race", + "racheter", + "racine", + "racler", + "raconter", + "radar", + "radio", + "rafale", + "rage", + "ragot", + "raideur", + "raie", + "rail", + "raison", + "ramasser", + "ramener", + "rampe", + "rance", + "rang", + "rapace", + "rapide", + "rapport", + "rarement", + "rasage", + "raser", + "rasoir", + "rassurer", + "rater", + "ratio", + "rature", + "ravage", + "ravir", + "rayer", + "rayon", + "rebond", + "recevoir", + "recherche", + "record", + "reculer", + "redevenir", + "refuser", + "regard", + "regretter", + "rein", + "rejeter", + "rejoindre", + "relation", + "relever", + "religion", + "remarquer", + "remettre", + "remise", + "remonter", + "remplir", + "remuer", + "rencontre", + "rendre", + "renier", + "renoncer", + "rentrer", + "renverser", + "repas", + "repli", + "reposer", + "reproche", + "requin", + "respect", + "ressembler", + "reste", + "retard", + "retenir", + "retirer", + "retour", + "retrouver", + "revenir", + "revoir", + "revue", + "rhume", + "ricaner", + "riche", + "rideau", + "ridicule", + "rien", + "rigide", + "rincer", + "rire", + "risquer", + "rituel", + "rivage", + "rive", + "robe", + "robot", + "robuste", + "rocade", + "roche", + "rodeur", + "rogner", + "roman", + "rompre", + "ronce", + "rondeur", + "ronger", + "roque", + "rose", + "rosir", + "rotation", + "rotule", + "roue", + "rouge", + "rouler", + "route", + "ruban", + "rubis", + "ruche", + "rude", + "ruelle", + "ruer", + "rugby", + "rugir", + "ruine", + "rumeur", + "rural", + "ruse", + "rustre", + "sable", + "sabot", + "sabre", + "sacre", + "sage", + "saint", + "saisir", + "salade", + "salive", + "salle", + "salon", + "salto", + "salut", + "salve", + "samba", + "sandale", + "sanguin", + "sapin", + "sarcasme", + "satisfaire", + "sauce", + "sauf", + "sauge", + "saule", + "sauna", + "sauter", + "sauver", + "savoir", + "science", + "scoop", + "score", + "second", + "secret", + "secte", + "seigneur", + "sein", + "seize", + "selle", + "selon", + "semaine", + "sembler", + "semer", + "semis", + "sensuel", + "sentir", + "sept", + "serpe", + "serrer", + "sertir", + "service", + "seuil", + "seulement", + "short", + "sien", + "sigle", + "signal", + "silence", + "silo", + "simple", + "singe", + "sinon", + "sinus", + "sioux", + "sirop", + "site", + "situation", + "skier", + "snob", + "sobre", + "social", + "socle", + "sodium", + "soigner", + "soir", + "soixante", + "soja", + "solaire", + "soldat", + "soleil", + "solide", + "solo", + "solvant", + "sombre", + "somme", + "somnoler", + "sondage", + "songeur", + "sonner", + "sorte", + "sosie", + "sottise", + "souci", + "soudain", + "souffrir", + "souhaiter", + "soulever", + "soumettre", + "soupe", + "sourd", + "soustraire", + "soutenir", + "souvent", + "soyeux", + "spectacle", + "sport", + "stade", + "stagiaire", + "stand", + "star", + "statue", + "stock", + "stop", + "store", + "style", + "suave", + "subir", + "sucre", + "suer", + "suffire", + "suie", + "suite", + "suivre", + "sujet", + "sulfite", + "supposer", + "surf", + "surprendre", + "surtout", + "surveiller", + "tabac", + "table", + "tabou", + "tache", + "tacler", + "tacot", + "tact", + "taie", + "taille", + "taire", + "talon", + "talus", + "tandis", + "tango", + "tanin", + "tant", + "taper", + "tapis", + "tard", + "tarif", + "tarot", + "tarte", + "tasse", + "taureau", + "taux", + "taverne", + "taxer", + "taxi", + "tellement", + "temple", + "tendre", + "tenir", + "tenter", + "tenu", + "terme", + "ternir", + "terre", + "test", + "texte", + "thym", + "tibia", + "tiers", + "tige", + "tipi", + "tique", + "tirer", + "tissu", + "titre", + "toast", + "toge", + "toile", + "toiser", + "toiture", + "tomber", + "tome", + "tonne", + "tonte", + "toque", + "torse", + "tortue", + "totem", + "toucher", + "toujours", + "tour", + "tousser", + "tout", + "toux", + "trace", + "train", + "trame", + "tranquille", + "travail", + "trembler", + "trente", + "tribu", + "trier", + "trio", + "tripe", + "triste", + "troc", + "trois", + "tromper", + "tronc", + "trop", + "trotter", + "trouer", + "truc", + "truite", + "tuba", + "tuer", + "tuile", + "turbo", + "tutu", + "tuyau", + "type", + "union", + "unique", + "unir", + "unisson", + "untel", + "urne", + "usage", + "user", + "usiner", + "usure", + "utile", + "vache", + "vague", + "vaincre", + "valeur", + "valoir", + "valser", + "valve", + "vampire", + "vaseux", + "vaste", + "veau", + "veille", + "veine", + "velours", + "velu", + "vendre", + "venir", + "vent", + "venue", + "verbe", + "verdict", + "version", + "vertige", + "verve", + "veste", + "veto", + "vexer", + "vice", + "victime", + "vide", + "vieil", + "vieux", + "vigie", + "vigne", + "ville", + "vingt", + "violent", + "virer", + "virus", + "visage", + "viser", + "visite", + "visuel", + "vitamine", + "vitrine", + "vivant", + "vivre", + "vocal", + "vodka", + "vogue", + "voici", + "voile", + "voir", + "voisin", + "voiture", + "volaille", + "volcan", + "voler", + "volt", + "votant", + "votre", + "vouer", + "vouloir", + "vous", + "voyage", + "voyou", + "vrac", + "vrai", + "yacht", + "yeti", + "yeux", + "yoga", + "zeste", + "zinc", + "zone", + "zoom" + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/german.h b/src/Mnemonics/german.h new file mode 100644 index 0000000..776b0e9 --- /dev/null +++ b/src/Mnemonics/german.h @@ -0,0 +1,1688 @@ +// Word list created by Monero contributor Shrikez +// +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file german.h + * + * \brief German word list and map. + */ + +#ifndef GERMAN_H +#define GERMAN_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class German: public Base + { + public: + German(): Base("Deutsch", std::vector({ + "Abakus", + "Abart", + "abbilden", + "Abbruch", + "Abdrift", + "Abendrot", + "Abfahrt", + "abfeuern", + "Abflug", + "abfragen", + "Abglanz", + "abhärten", + "abheben", + "Abhilfe", + "Abitur", + "Abkehr", + "Ablauf", + "ablecken", + "Ablösung", + "Abnehmer", + "abnutzen", + "Abonnent", + "Abrasion", + "Abrede", + "abrüsten", + "Absicht", + "Absprung", + "Abstand", + "absuchen", + "Abteil", + "Abundanz", + "abwarten", + "Abwurf", + "Abzug", + "Achse", + "Achtung", + "Acker", + "Aderlass", + "Adler", + "Admiral", + "Adresse", + "Affe", + "Affront", + "Afrika", + "Aggregat", + "Agilität", + "ähneln", + "Ahnung", + "Ahorn", + "Akazie", + "Akkord", + "Akrobat", + "Aktfoto", + "Aktivist", + "Albatros", + "Alchimie", + "Alemanne", + "Alibi", + "Alkohol", + "Allee", + "Allüre", + "Almosen", + "Almweide", + "Aloe", + "Alpaka", + "Alpental", + "Alphabet", + "Alpinist", + "Alraune", + "Altbier", + "Alter", + "Altflöte", + "Altruist", + "Alublech", + "Aludose", + "Amateur", + "Amazonas", + "Ameise", + "Amnesie", + "Amok", + "Ampel", + "Amphibie", + "Ampulle", + "Amsel", + "Amulett", + "Anakonda", + "Analogie", + "Ananas", + "Anarchie", + "Anatomie", + "Anbau", + "Anbeginn", + "anbieten", + "Anblick", + "ändern", + "andocken", + "Andrang", + "anecken", + "Anflug", + "Anfrage", + "Anführer", + "Angebot", + "Angler", + "Anhalter", + "Anhöhe", + "Animator", + "Anis", + "Anker", + "ankleben", + "Ankunft", + "Anlage", + "anlocken", + "Anmut", + "Annahme", + "Anomalie", + "Anonymus", + "Anorak", + "anpeilen", + "Anrecht", + "Anruf", + "Ansage", + "Anschein", + "Ansicht", + "Ansporn", + "Anteil", + "Antlitz", + "Antrag", + "Antwort", + "Anwohner", + "Aorta", + "Apfel", + "Appetit", + "Applaus", + "Aquarium", + "Arbeit", + "Arche", + "Argument", + "Arktis", + "Armband", + "Aroma", + "Asche", + "Askese", + "Asphalt", + "Asteroid", + "Ästhetik", + "Astronom", + "Atelier", + "Athlet", + "Atlantik", + "Atmung", + "Audienz", + "aufatmen", + "Auffahrt", + "aufholen", + "aufregen", + "Aufsatz", + "Auftritt", + "Aufwand", + "Augapfel", + "Auktion", + "Ausbruch", + "Ausflug", + "Ausgabe", + "Aushilfe", + "Ausland", + "Ausnahme", + "Aussage", + "Autobahn", + "Avocado", + "Axthieb", + "Bach", + "backen", + "Badesee", + "Bahnhof", + "Balance", + "Balkon", + "Ballett", + "Balsam", + "Banane", + "Bandage", + "Bankett", + "Barbar", + "Barde", + "Barett", + "Bargeld", + "Barkasse", + "Barriere", + "Bart", + "Bass", + "Bastler", + "Batterie", + "Bauch", + "Bauer", + "Bauholz", + "Baujahr", + "Baum", + "Baustahl", + "Bauteil", + "Bauweise", + "Bazar", + "beachten", + "Beatmung", + "beben", + "Becher", + "Becken", + "bedanken", + "beeilen", + "beenden", + "Beere", + "befinden", + "Befreier", + "Begabung", + "Begierde", + "begrüßen", + "Beiboot", + "Beichte", + "Beifall", + "Beigabe", + "Beil", + "Beispiel", + "Beitrag", + "beizen", + "bekommen", + "beladen", + "Beleg", + "bellen", + "belohnen", + "Bemalung", + "Bengel", + "Benutzer", + "Benzin", + "beraten", + "Bereich", + "Bergluft", + "Bericht", + "Bescheid", + "Besitz", + "besorgen", + "Bestand", + "Besuch", + "betanken", + "beten", + "betören", + "Bett", + "Beule", + "Beute", + "Bewegung", + "bewirken", + "Bewohner", + "bezahlen", + "Bezug", + "biegen", + "Biene", + "Bierzelt", + "bieten", + "Bikini", + "Bildung", + "Billard", + "binden", + "Biobauer", + "Biologe", + "Bionik", + "Biotop", + "Birke", + "Bison", + "Bitte", + "Biwak", + "Bizeps", + "blasen", + "Blatt", + "Blauwal", + "Blende", + "Blick", + "Blitz", + "Blockade", + "Blödelei", + "Blondine", + "Blues", + "Blume", + "Blut", + "Bodensee", + "Bogen", + "Boje", + "Bollwerk", + "Bonbon", + "Bonus", + "Boot", + "Bordarzt", + "Börse", + "Böschung", + "Boudoir", + "Boxkampf", + "Boykott", + "Brahms", + "Brandung", + "Brauerei", + "Brecher", + "Breitaxt", + "Bremse", + "brennen", + "Brett", + "Brief", + "Brigade", + "Brillanz", + "bringen", + "brodeln", + "Brosche", + "Brötchen", + "Brücke", + "Brunnen", + "Brüste", + "Brutofen", + "Buch", + "Büffel", + "Bugwelle", + "Bühne", + "Buletten", + "Bullauge", + "Bumerang", + "bummeln", + "Buntglas", + "Bürde", + "Burgherr", + "Bursche", + "Busen", + "Buslinie", + "Bussard", + "Butangas", + "Butter", + "Cabrio", + "campen", + "Captain", + "Cartoon", + "Cello", + "Chalet", + "Charisma", + "Chefarzt", + "Chiffon", + "Chipsatz", + "Chirurg", + "Chor", + "Chronik", + "Chuzpe", + "Clubhaus", + "Cockpit", + "Codewort", + "Cognac", + "Coladose", + "Computer", + "Coupon", + "Cousin", + "Cracking", + "Crash", + "Curry", + "Dach", + "Dackel", + "daddeln", + "daliegen", + "Dame", + "Dammbau", + "Dämon", + "Dampflok", + "Dank", + "Darm", + "Datei", + "Datsche", + "Datteln", + "Datum", + "Dauer", + "Daunen", + "Deckel", + "Decoder", + "Defekt", + "Degen", + "Dehnung", + "Deiche", + "Dekade", + "Dekor", + "Delfin", + "Demut", + "denken", + "Deponie", + "Design", + "Desktop", + "Dessert", + "Detail", + "Detektiv", + "Dezibel", + "Diadem", + "Diagnose", + "Dialekt", + "Diamant", + "Dichter", + "Dickicht", + "Diesel", + "Diktat", + "Diplom", + "Direktor", + "Dirne", + "Diskurs", + "Distanz", + "Docht", + "Dohle", + "Dolch", + "Domäne", + "Donner", + "Dorade", + "Dorf", + "Dörrobst", + "Dorsch", + "Dossier", + "Dozent", + "Drachen", + "Draht", + "Drama", + "Drang", + "Drehbuch", + "Dreieck", + "Dressur", + "Drittel", + "Drossel", + "Druck", + "Duell", + "Duft", + "Düne", + "Dünung", + "dürfen", + "Duschbad", + "Düsenjet", + "Dynamik", + "Ebbe", + "Echolot", + "Echse", + "Eckball", + "Edding", + "Edelweiß", + "Eden", + "Edition", + "Efeu", + "Effekte", + "Egoismus", + "Ehre", + "Eiablage", + "Eiche", + "Eidechse", + "Eidotter", + "Eierkopf", + "Eigelb", + "Eiland", + "Eilbote", + "Eimer", + "einatmen", + "Einband", + "Eindruck", + "Einfall", + "Eingang", + "Einkauf", + "einladen", + "Einöde", + "Einrad", + "Eintopf", + "Einwurf", + "Einzug", + "Eisbär", + "Eisen", + "Eishöhle", + "Eismeer", + "Eiweiß", + "Ekstase", + "Elan", + "Elch", + "Elefant", + "Eleganz", + "Element", + "Elfe", + "Elite", + "Elixier", + "Ellbogen", + "Eloquenz", + "Emigrant", + "Emission", + "Emotion", + "Empathie", + "Empfang", + "Endzeit", + "Energie", + "Engpass", + "Enkel", + "Enklave", + "Ente", + "entheben", + "Entität", + "entladen", + "Entwurf", + "Episode", + "Epoche", + "erachten", + "Erbauer", + "erblühen", + "Erdbeere", + "Erde", + "Erdgas", + "Erdkunde", + "Erdnuss", + "Erdöl", + "Erdteil", + "Ereignis", + "Eremit", + "erfahren", + "Erfolg", + "erfreuen", + "erfüllen", + "Ergebnis", + "erhitzen", + "erkalten", + "erkennen", + "erleben", + "Erlösung", + "ernähren", + "erneuern", + "Ernte", + "Eroberer", + "eröffnen", + "Erosion", + "Erotik", + "Erpel", + "erraten", + "Erreger", + "erröten", + "Ersatz", + "Erstflug", + "Ertrag", + "Eruption", + "erwarten", + "erwidern", + "Erzbau", + "Erzeuger", + "erziehen", + "Esel", + "Eskimo", + "Eskorte", + "Espe", + "Espresso", + "essen", + "Etage", + "Etappe", + "Etat", + "Ethik", + "Etikett", + "Etüde", + "Eule", + "Euphorie", + "Europa", + "Everest", + "Examen", + "Exil", + "Exodus", + "Extrakt", + "Fabel", + "Fabrik", + "Fachmann", + "Fackel", + "Faden", + "Fagott", + "Fahne", + "Faible", + "Fairness", + "Fakt", + "Fakultät", + "Falke", + "Fallobst", + "Fälscher", + "Faltboot", + "Familie", + "Fanclub", + "Fanfare", + "Fangarm", + "Fantasie", + "Farbe", + "Farmhaus", + "Farn", + "Fasan", + "Faser", + "Fassung", + "fasten", + "Faulheit", + "Fauna", + "Faust", + "Favorit", + "Faxgerät", + "Fazit", + "fechten", + "Federboa", + "Fehler", + "Feier", + "Feige", + "feilen", + "Feinripp", + "Feldbett", + "Felge", + "Fellpony", + "Felswand", + "Ferien", + "Ferkel", + "Fernweh", + "Ferse", + "Fest", + "Fettnapf", + "Feuer", + "Fiasko", + "Fichte", + "Fiktion", + "Film", + "Filter", + "Filz", + "Finanzen", + "Findling", + "Finger", + "Fink", + "Finnwal", + "Fisch", + "Fitness", + "Fixpunkt", + "Fixstern", + "Fjord", + "Flachbau", + "Flagge", + "Flamenco", + "Flanke", + "Flasche", + "Flaute", + "Fleck", + "Flegel", + "flehen", + "Fleisch", + "fliegen", + "Flinte", + "Flirt", + "Flocke", + "Floh", + "Floskel", + "Floß", + "Flöte", + "Flugzeug", + "Flunder", + "Flusstal", + "Flutung", + "Fockmast", + "Fohlen", + "Föhnlage", + "Fokus", + "folgen", + "Foliant", + "Folklore", + "Fontäne", + "Förde", + "Forelle", + "Format", + "Forscher", + "Fortgang", + "Forum", + "Fotograf", + "Frachter", + "Fragment", + "Fraktion", + "fräsen", + "Frauenpo", + "Freak", + "Fregatte", + "Freiheit", + "Freude", + "Frieden", + "Frohsinn", + "Frosch", + "Frucht", + "Frühjahr", + "Fuchs", + "Fügung", + "fühlen", + "Füller", + "Fundbüro", + "Funkboje", + "Funzel", + "Furnier", + "Fürsorge", + "Fusel", + "Fußbad", + "Futteral", + "Gabelung", + "gackern", + "Gage", + "gähnen", + "Galaxie", + "Galeere", + "Galopp", + "Gameboy", + "Gamsbart", + "Gandhi", + "Gang", + "Garage", + "Gardine", + "Garküche", + "Garten", + "Gasthaus", + "Gattung", + "gaukeln", + "Gazelle", + "Gebäck", + "Gebirge", + "Gebräu", + "Geburt", + "Gedanke", + "Gedeck", + "Gedicht", + "Gefahr", + "Gefieder", + "Geflügel", + "Gefühl", + "Gegend", + "Gehirn", + "Gehöft", + "Gehweg", + "Geige", + "Geist", + "Gelage", + "Geld", + "Gelenk", + "Gelübde", + "Gemälde", + "Gemeinde", + "Gemüse", + "genesen", + "Genuss", + "Gepäck", + "Geranie", + "Gericht", + "Germane", + "Geruch", + "Gesang", + "Geschenk", + "Gesetz", + "Gesindel", + "Gesöff", + "Gespan", + "Gestade", + "Gesuch", + "Getier", + "Getränk", + "Getümmel", + "Gewand", + "Geweih", + "Gewitter", + "Gewölbe", + "Geysir", + "Giftzahn", + "Gipfel", + "Giraffe", + "Gitarre", + "glänzen", + "Glasauge", + "Glatze", + "Gleis", + "Globus", + "Glück", + "glühen", + "Glutofen", + "Goldzahn", + "Gondel", + "gönnen", + "Gottheit", + "graben", + "Grafik", + "Grashalm", + "Graugans", + "greifen", + "Grenze", + "grillen", + "Groschen", + "Grotte", + "Grube", + "Grünalge", + "Gruppe", + "gruseln", + "Gulasch", + "Gummibär", + "Gurgel", + "Gürtel", + "Güterzug", + "Haarband", + "Habicht", + "hacken", + "hadern", + "Hafen", + "Hagel", + "Hähnchen", + "Haifisch", + "Haken", + "Halbaffe", + "Halsader", + "halten", + "Halunke", + "Handbuch", + "Hanf", + "Harfe", + "Harnisch", + "härten", + "Harz", + "Hasenohr", + "Haube", + "hauchen", + "Haupt", + "Haut", + "Havarie", + "Hebamme", + "hecheln", + "Heck", + "Hedonist", + "Heiler", + "Heimat", + "Heizung", + "Hektik", + "Held", + "helfen", + "Helium", + "Hemd", + "hemmen", + "Hengst", + "Herd", + "Hering", + "Herkunft", + "Hermelin", + "Herrchen", + "Herzdame", + "Heulboje", + "Hexe", + "Hilfe", + "Himbeere", + "Himmel", + "Hingabe", + "hinhören", + "Hinweis", + "Hirsch", + "Hirte", + "Hitzkopf", + "Hobel", + "Hochform", + "Hocker", + "hoffen", + "Hofhund", + "Hofnarr", + "Höhenzug", + "Hohlraum", + "Hölle", + "Holzboot", + "Honig", + "Honorar", + "horchen", + "Hörprobe", + "Höschen", + "Hotel", + "Hubraum", + "Hufeisen", + "Hügel", + "huldigen", + "Hülle", + "Humbug", + "Hummer", + "Humor", + "Hund", + "Hunger", + "Hupe", + "Hürde", + "Hurrikan", + "Hydrant", + "Hypnose", + "Ibis", + "Idee", + "Idiot", + "Igel", + "Illusion", + "Imitat", + "impfen", + "Import", + "Inferno", + "Ingwer", + "Inhalte", + "Inland", + "Insekt", + "Ironie", + "Irrfahrt", + "Irrtum", + "Isolator", + "Istwert", + "Jacke", + "Jade", + "Jagdhund", + "Jäger", + "Jaguar", + "Jahr", + "Jähzorn", + "Jazzfest", + "Jetpilot", + "jobben", + "Jochbein", + "jodeln", + "Jodsalz", + "Jolle", + "Journal", + "Jubel", + "Junge", + "Junimond", + "Jupiter", + "Jutesack", + "Juwel", + "Kabarett", + "Kabine", + "Kabuff", + "Käfer", + "Kaffee", + "Kahlkopf", + "Kaimauer", + "Kajüte", + "Kaktus", + "Kaliber", + "Kaltluft", + "Kamel", + "kämmen", + "Kampagne", + "Kanal", + "Känguru", + "Kanister", + "Kanone", + "Kante", + "Kanu", + "kapern", + "Kapitän", + "Kapuze", + "Karneval", + "Karotte", + "Käsebrot", + "Kasper", + "Kastanie", + "Katalog", + "Kathode", + "Katze", + "kaufen", + "Kaugummi", + "Kauz", + "Kehle", + "Keilerei", + "Keksdose", + "Kellner", + "Keramik", + "Kerze", + "Kessel", + "Kette", + "keuchen", + "kichern", + "Kielboot", + "Kindheit", + "Kinnbart", + "Kinosaal", + "Kiosk", + "Kissen", + "Klammer", + "Klang", + "Klapprad", + "Klartext", + "kleben", + "Klee", + "Kleinod", + "Klima", + "Klingel", + "Klippe", + "Klischee", + "Kloster", + "Klugheit", + "Klüngel", + "kneten", + "Knie", + "Knöchel", + "knüpfen", + "Kobold", + "Kochbuch", + "Kohlrabi", + "Koje", + "Kokosöl", + "Kolibri", + "Kolumne", + "Kombüse", + "Komiker", + "kommen", + "Konto", + "Konzept", + "Kopfkino", + "Kordhose", + "Korken", + "Korsett", + "Kosename", + "Krabbe", + "Krach", + "Kraft", + "Krähe", + "Kralle", + "Krapfen", + "Krater", + "kraulen", + "Kreuz", + "Krokodil", + "Kröte", + "Kugel", + "Kuhhirt", + "Kühnheit", + "Künstler", + "Kurort", + "Kurve", + "Kurzfilm", + "kuscheln", + "küssen", + "Kutter", + "Labor", + "lachen", + "Lackaffe", + "Ladeluke", + "Lagune", + "Laib", + "Lakritze", + "Lammfell", + "Land", + "Langmut", + "Lappalie", + "Last", + "Laterne", + "Latzhose", + "Laubsäge", + "laufen", + "Laune", + "Lausbub", + "Lavasee", + "Leben", + "Leder", + "Leerlauf", + "Lehm", + "Lehrer", + "leihen", + "Lektüre", + "Lenker", + "Lerche", + "Leseecke", + "Leuchter", + "Lexikon", + "Libelle", + "Libido", + "Licht", + "Liebe", + "liefern", + "Liftboy", + "Limonade", + "Lineal", + "Linoleum", + "List", + "Liveband", + "Lobrede", + "locken", + "Löffel", + "Logbuch", + "Logik", + "Lohn", + "Loipe", + "Lokal", + "Lorbeer", + "Lösung", + "löten", + "Lottofee", + "Löwe", + "Luchs", + "Luder", + "Luftpost", + "Luke", + "Lümmel", + "Lunge", + "lutschen", + "Luxus", + "Macht", + "Magazin", + "Magier", + "Magnet", + "mähen", + "Mahlzeit", + "Mahnmal", + "Maibaum", + "Maisbrei", + "Makel", + "malen", + "Mammut", + "Maniküre", + "Mantel", + "Marathon", + "Marder", + "Marine", + "Marke", + "Marmor", + "Märzluft", + "Maske", + "Maßanzug", + "Maßkrug", + "Mastkorb", + "Material", + "Matratze", + "Mauerbau", + "Maulkorb", + "Mäuschen", + "Mäzen", + "Medium", + "Meinung", + "melden", + "Melodie", + "Mensch", + "Merkmal", + "Messe", + "Metall", + "Meteor", + "Methode", + "Metzger", + "Mieze", + "Milchkuh", + "Mimose", + "Minirock", + "Minute", + "mischen", + "Missetat", + "mitgehen", + "Mittag", + "Mixtape", + "Möbel", + "Modul", + "mögen", + "Möhre", + "Molch", + "Moment", + "Monat", + "Mondflug", + "Monitor", + "Monokini", + "Monster", + "Monument", + "Moorhuhn", + "Moos", + "Möpse", + "Moral", + "Mörtel", + "Motiv", + "Motorrad", + "Möwe", + "Mühe", + "Mulatte", + "Müller", + "Mumie", + "Mund", + "Münze", + "Muschel", + "Muster", + "Mythos", + "Nabel", + "Nachtzug", + "Nackedei", + "Nagel", + "Nähe", + "Nähnadel", + "Namen", + "Narbe", + "Narwal", + "Nasenbär", + "Natur", + "Nebel", + "necken", + "Neffe", + "Neigung", + "Nektar", + "Nenner", + "Neptun", + "Nerz", + "Nessel", + "Nestbau", + "Netz", + "Neubau", + "Neuerung", + "Neugier", + "nicken", + "Niere", + "Nilpferd", + "nisten", + "Nocke", + "Nomade", + "Nordmeer", + "Notdurft", + "Notstand", + "Notwehr", + "Nudismus", + "Nuss", + "Nutzhanf", + "Oase", + "Obdach", + "Oberarzt", + "Objekt", + "Oboe", + "Obsthain", + "Ochse", + "Odyssee", + "Ofenholz", + "öffnen", + "Ohnmacht", + "Ohrfeige", + "Ohrwurm", + "Ökologie", + "Oktave", + "Ölberg", + "Olive", + "Ölkrise", + "Omelett", + "Onkel", + "Oper", + "Optiker", + "Orange", + "Orchidee", + "ordnen", + "Orgasmus", + "Orkan", + "Ortskern", + "Ortung", + "Ostasien", + "Ozean", + "Paarlauf", + "Packeis", + "paddeln", + "Paket", + "Palast", + "Pandabär", + "Panik", + "Panorama", + "Panther", + "Papagei", + "Papier", + "Paprika", + "Paradies", + "Parka", + "Parodie", + "Partner", + "Passant", + "Patent", + "Patzer", + "Pause", + "Pavian", + "Pedal", + "Pegel", + "peilen", + "Perle", + "Person", + "Pfad", + "Pfau", + "Pferd", + "Pfleger", + "Physik", + "Pier", + "Pilotwal", + "Pinzette", + "Piste", + "Plakat", + "Plankton", + "Platin", + "Plombe", + "plündern", + "Pobacke", + "Pokal", + "polieren", + "Popmusik", + "Porträt", + "Posaune", + "Postamt", + "Pottwal", + "Pracht", + "Pranke", + "Preis", + "Primat", + "Prinzip", + "Protest", + "Proviant", + "Prüfung", + "Pubertät", + "Pudding", + "Pullover", + "Pulsader", + "Punkt", + "Pute", + "Putsch", + "Puzzle", + "Python", + "quaken", + "Qualle", + "Quark", + "Quellsee", + "Querkopf", + "Quitte", + "Quote", + "Rabauke", + "Rache", + "Radclub", + "Radhose", + "Radio", + "Radtour", + "Rahmen", + "Rampe", + "Randlage", + "Ranzen", + "Rapsöl", + "Raserei", + "rasten", + "Rasur", + "Rätsel", + "Raubtier", + "Raumzeit", + "Rausch", + "Reaktor", + "Realität", + "Rebell", + "Rede", + "Reetdach", + "Regatta", + "Regen", + "Rehkitz", + "Reifen", + "Reim", + "Reise", + "Reizung", + "Rekord", + "Relevanz", + "Rennboot", + "Respekt", + "Restmüll", + "retten", + "Reue", + "Revolte", + "Rhetorik", + "Rhythmus", + "Richtung", + "Riegel", + "Rindvieh", + "Rippchen", + "Ritter", + "Robbe", + "Roboter", + "Rockband", + "Rohdaten", + "Roller", + "Roman", + "röntgen", + "Rose", + "Rosskur", + "Rost", + "Rotahorn", + "Rotglut", + "Rotznase", + "Rubrik", + "Rückweg", + "Rufmord", + "Ruhe", + "Ruine", + "Rumpf", + "Runde", + "Rüstung", + "rütteln", + "Saaltür", + "Saatguts", + "Säbel", + "Sachbuch", + "Sack", + "Saft", + "sagen", + "Sahneeis", + "Salat", + "Salbe", + "Salz", + "Sammlung", + "Samt", + "Sandbank", + "Sanftmut", + "Sardine", + "Satire", + "Sattel", + "Satzbau", + "Sauerei", + "Saum", + "Säure", + "Schall", + "Scheitel", + "Schiff", + "Schlager", + "Schmied", + "Schnee", + "Scholle", + "Schrank", + "Schulbus", + "Schwan", + "Seeadler", + "Seefahrt", + "Seehund", + "Seeufer", + "segeln", + "Sehnerv", + "Seide", + "Seilzug", + "Senf", + "Sessel", + "Seufzer", + "Sexgott", + "Sichtung", + "Signal", + "Silber", + "singen", + "Sinn", + "Sirup", + "Sitzbank", + "Skandal", + "Skikurs", + "Skipper", + "Skizze", + "Smaragd", + "Socke", + "Sohn", + "Sommer", + "Songtext", + "Sorte", + "Spagat", + "Spannung", + "Spargel", + "Specht", + "Speiseöl", + "Spiegel", + "Sport", + "spülen", + "Stadtbus", + "Stall", + "Stärke", + "Stativ", + "staunen", + "Stern", + "Stiftung", + "Stollen", + "Strömung", + "Sturm", + "Substanz", + "Südalpen", + "Sumpf", + "surfen", + "Tabak", + "Tafel", + "Tagebau", + "takeln", + "Taktung", + "Talsohle", + "Tand", + "Tanzbär", + "Tapir", + "Tarantel", + "Tarnname", + "Tasse", + "Tatnacht", + "Tatsache", + "Tatze", + "Taube", + "tauchen", + "Taufpate", + "Taumel", + "Teelicht", + "Teich", + "teilen", + "Tempo", + "Tenor", + "Terrasse", + "Testflug", + "Theater", + "Thermik", + "ticken", + "Tiefflug", + "Tierart", + "Tigerhai", + "Tinte", + "Tischler", + "toben", + "Toleranz", + "Tölpel", + "Tonband", + "Topf", + "Topmodel", + "Torbogen", + "Torlinie", + "Torte", + "Tourist", + "Tragesel", + "trampeln", + "Trapez", + "Traum", + "treffen", + "Trennung", + "Treue", + "Trick", + "trimmen", + "Trödel", + "Trost", + "Trumpf", + "tüfteln", + "Turban", + "Turm", + "Übermut", + "Ufer", + "Uhrwerk", + "umarmen", + "Umbau", + "Umfeld", + "Umgang", + "Umsturz", + "Unart", + "Unfug", + "Unimog", + "Unruhe", + "Unwucht", + "Uranerz", + "Urlaub", + "Urmensch", + "Utopie", + "Vakuum", + "Valuta", + "Vandale", + "Vase", + "Vektor", + "Ventil", + "Verb", + "Verdeck", + "Verfall", + "Vergaser", + "verhexen", + "Verlag", + "Vers", + "Vesper", + "Vieh", + "Viereck", + "Vinyl", + "Virus", + "Vitrine", + "Vollblut", + "Vorbote", + "Vorrat", + "Vorsicht", + "Vulkan", + "Wachstum", + "Wade", + "Wagemut", + "Wahlen", + "Wahrheit", + "Wald", + "Walhai", + "Wallach", + "Walnuss", + "Walzer", + "wandeln", + "Wanze", + "wärmen", + "Warnruf", + "Wäsche", + "Wasser", + "Weberei", + "wechseln", + "Wegegeld", + "wehren", + "Weiher", + "Weinglas", + "Weißbier", + "Weitwurf", + "Welle", + "Weltall", + "Werkbank", + "Werwolf", + "Wetter", + "wiehern", + "Wildgans", + "Wind", + "Wohl", + "Wohnort", + "Wolf", + "Wollust", + "Wortlaut", + "Wrack", + "Wunder", + "Wurfaxt", + "Wurst", + "Yacht", + "Yeti", + "Zacke", + "Zahl", + "zähmen", + "Zahnfee", + "Zäpfchen", + "Zaster", + "Zaumzeug", + "Zebra", + "zeigen", + "Zeitlupe", + "Zellkern", + "Zeltdach", + "Zensor", + "Zerfall", + "Zeug", + "Ziege", + "Zielfoto", + "Zimteis", + "Zobel", + "Zollhund", + "Zombie", + "Zöpfe", + "Zucht", + "Zufahrt", + "Zugfahrt", + "Zugvogel", + "Zündung", + "Zweck", + "Zyklop" + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/italian.h b/src/Mnemonics/italian.h new file mode 100644 index 0000000..ff47715 --- /dev/null +++ b/src/Mnemonics/italian.h @@ -0,0 +1,1688 @@ +// Word list created by Monero contributor Shrikez +// +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file italian.h + * + * \brief Italian word list and map. + */ + +#ifndef ITALIAN_H +#define ITALIAN_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Italian: public Base + { + public: + Italian(): Base("Italiano", std::vector({ + "abbinare", + "abbonato", + "abisso", + "abitare", + "abominio", + "accadere", + "accesso", + "acciaio", + "accordo", + "accumulo", + "acido", + "acqua", + "acrobata", + "acustico", + "adattare", + "addetto", + "addio", + "addome", + "adeguato", + "aderire", + "adorare", + "adottare", + "adozione", + "adulto", + "aereo", + "aerobica", + "affare", + "affetto", + "affidare", + "affogato", + "affronto", + "africano", + "afrodite", + "agenzia", + "aggancio", + "aggeggio", + "aggiunta", + "agio", + "agire", + "agitare", + "aglio", + "agnello", + "agosto", + "aiutare", + "albero", + "albo", + "alce", + "alchimia", + "alcool", + "alfabeto", + "algebra", + "alimento", + "allarme", + "alleanza", + "allievo", + "alloggio", + "alluce", + "alpi", + "alterare", + "altro", + "aluminio", + "amante", + "amarezza", + "ambiente", + "ambrosia", + "america", + "amico", + "ammalare", + "ammirare", + "amnesia", + "amnistia", + "amore", + "ampliare", + "amputare", + "analisi", + "anamnesi", + "ananas", + "anarchia", + "anatra", + "anca", + "ancorato", + "andare", + "androide", + "aneddoto", + "anello", + "angelo", + "angolino", + "anguilla", + "anidride", + "anima", + "annegare", + "anno", + "annuncio", + "anomalia", + "antenna", + "anticipo", + "aperto", + "apostolo", + "appalto", + "appello", + "appiglio", + "applauso", + "appoggio", + "appurare", + "aprile", + "aquila", + "arabo", + "arachidi", + "aragosta", + "arancia", + "arbitrio", + "archivio", + "arco", + "argento", + "argilla", + "aria", + "ariete", + "arma", + "armonia", + "aroma", + "arrivare", + "arrosto", + "arsenale", + "arte", + "artiglio", + "asfalto", + "asfissia", + "asino", + "asparagi", + "aspirina", + "assalire", + "assegno", + "assolto", + "assurdo", + "asta", + "astratto", + "atlante", + "atletica", + "atomo", + "atropina", + "attacco", + "attesa", + "attico", + "atto", + "attrarre", + "auguri", + "aula", + "aumento", + "aurora", + "auspicio", + "autista", + "auto", + "autunno", + "avanzare", + "avarizia", + "avere", + "aviatore", + "avido", + "avorio", + "avvenire", + "avviso", + "avvocato", + "azienda", + "azione", + "azzardo", + "azzurro", + "babbuino", + "bacio", + "badante", + "baffi", + "bagaglio", + "bagliore", + "bagno", + "balcone", + "balena", + "ballare", + "balordo", + "balsamo", + "bambola", + "bancomat", + "banda", + "barato", + "barba", + "barista", + "barriera", + "basette", + "basilico", + "bassista", + "bastare", + "battello", + "bavaglio", + "beccare", + "beduino", + "bellezza", + "bene", + "benzina", + "berretto", + "bestia", + "bevitore", + "bianco", + "bibbia", + "biberon", + "bibita", + "bici", + "bidone", + "bilancia", + "biliardo", + "binario", + "binocolo", + "biologia", + "biondina", + "biopsia", + "biossido", + "birbante", + "birra", + "biscotto", + "bisogno", + "bistecca", + "bivio", + "blindare", + "bloccare", + "bocca", + "bollire", + "bombola", + "bonifico", + "borghese", + "borsa", + "bottino", + "botulino", + "braccio", + "bradipo", + "branco", + "bravo", + "bresaola", + "bretelle", + "brevetto", + "briciola", + "brigante", + "brillare", + "brindare", + "brivido", + "broccoli", + "brontolo", + "bruciare", + "brufolo", + "bucare", + "buddista", + "budino", + "bufera", + "buffo", + "bugiardo", + "buio", + "buono", + "burrone", + "bussola", + "bustina", + "buttare", + "cabernet", + "cabina", + "cacao", + "cacciare", + "cactus", + "cadavere", + "caffe", + "calamari", + "calcio", + "caldaia", + "calmare", + "calunnia", + "calvario", + "calzone", + "cambiare", + "camera", + "camion", + "cammello", + "campana", + "canarino", + "cancello", + "candore", + "cane", + "canguro", + "cannone", + "canoa", + "cantare", + "canzone", + "caos", + "capanna", + "capello", + "capire", + "capo", + "capperi", + "capra", + "capsula", + "caraffa", + "carbone", + "carciofo", + "cardigan", + "carenza", + "caricare", + "carota", + "carrello", + "carta", + "casa", + "cascare", + "caserma", + "cashmere", + "casino", + "cassetta", + "castello", + "catalogo", + "catena", + "catorcio", + "cattivo", + "causa", + "cauzione", + "cavallo", + "caverna", + "caviglia", + "cavo", + "cazzotto", + "celibato", + "cemento", + "cenare", + "centrale", + "ceramica", + "cercare", + "ceretta", + "cerniera", + "certezza", + "cervello", + "cessione", + "cestino", + "cetriolo", + "chiave", + "chiedere", + "chilo", + "chimera", + "chiodo", + "chirurgo", + "chitarra", + "chiudere", + "ciabatta", + "ciao", + "cibo", + "ciccia", + "cicerone", + "ciclone", + "cicogna", + "cielo", + "cifra", + "cigno", + "ciliegia", + "cimitero", + "cinema", + "cinque", + "cintura", + "ciondolo", + "ciotola", + "cipolla", + "cippato", + "circuito", + "cisterna", + "citofono", + "ciuccio", + "civetta", + "civico", + "clausola", + "cliente", + "clima", + "clinica", + "cobra", + "coccole", + "cocktail", + "cocomero", + "codice", + "coesione", + "cogliere", + "cognome", + "colla", + "colomba", + "colpire", + "coltello", + "comando", + "comitato", + "commedia", + "comodino", + "compagna", + "comune", + "concerto", + "condotto", + "conforto", + "congiura", + "coniglio", + "consegna", + "conto", + "convegno", + "coperta", + "copia", + "coprire", + "corazza", + "corda", + "corleone", + "cornice", + "corona", + "corpo", + "corrente", + "corsa", + "cortesia", + "corvo", + "coso", + "costume", + "cotone", + "cottura", + "cozza", + "crampo", + "cratere", + "cravatta", + "creare", + "credere", + "crema", + "crescere", + "crimine", + "criterio", + "croce", + "crollare", + "cronaca", + "crostata", + "croupier", + "cubetto", + "cucciolo", + "cucina", + "cultura", + "cuoco", + "cuore", + "cupido", + "cupola", + "cura", + "curva", + "cuscino", + "custode", + "danzare", + "data", + "decennio", + "decidere", + "decollo", + "dedicare", + "dedurre", + "definire", + "delegare", + "delfino", + "delitto", + "demone", + "dentista", + "denuncia", + "deposito", + "derivare", + "deserto", + "designer", + "destino", + "detonare", + "dettagli", + "diagnosi", + "dialogo", + "diamante", + "diario", + "diavolo", + "dicembre", + "difesa", + "digerire", + "digitare", + "diluvio", + "dinamica", + "dipinto", + "diploma", + "diramare", + "dire", + "dirigere", + "dirupo", + "discesa", + "disdetta", + "disegno", + "disporre", + "dissenso", + "distacco", + "dito", + "ditta", + "diva", + "divenire", + "dividere", + "divorare", + "docente", + "dolcetto", + "dolore", + "domatore", + "domenica", + "dominare", + "donatore", + "donna", + "dorato", + "dormire", + "dorso", + "dosaggio", + "dottore", + "dovere", + "download", + "dragone", + "dramma", + "dubbio", + "dubitare", + "duetto", + "durata", + "ebbrezza", + "eccesso", + "eccitare", + "eclissi", + "economia", + "edera", + "edificio", + "editore", + "edizione", + "educare", + "effetto", + "egitto", + "egiziano", + "elastico", + "elefante", + "eleggere", + "elemento", + "elenco", + "elezione", + "elmetto", + "elogio", + "embrione", + "emergere", + "emettere", + "eminenza", + "emisfero", + "emozione", + "empatia", + "energia", + "enfasi", + "enigma", + "entrare", + "enzima", + "epidemia", + "epilogo", + "episodio", + "epoca", + "equivoco", + "erba", + "erede", + "eroe", + "erotico", + "errore", + "eruzione", + "esaltare", + "esame", + "esaudire", + "eseguire", + "esempio", + "esigere", + "esistere", + "esito", + "esperto", + "espresso", + "essere", + "estasi", + "esterno", + "estrarre", + "eterno", + "etica", + "euforico", + "europa", + "evacuare", + "evasione", + "evento", + "evidenza", + "evitare", + "evolvere", + "fabbrica", + "facciata", + "fagiano", + "fagotto", + "falco", + "fame", + "famiglia", + "fanale", + "fango", + "fantasia", + "farfalla", + "farmacia", + "faro", + "fase", + "fastidio", + "faticare", + "fatto", + "favola", + "febbre", + "femmina", + "femore", + "fenomeno", + "fermata", + "feromoni", + "ferrari", + "fessura", + "festa", + "fiaba", + "fiamma", + "fianco", + "fiat", + "fibbia", + "fidare", + "fieno", + "figa", + "figlio", + "figura", + "filetto", + "filmato", + "filosofo", + "filtrare", + "finanza", + "finestra", + "fingere", + "finire", + "finta", + "finzione", + "fiocco", + "fioraio", + "firewall", + "firmare", + "fisico", + "fissare", + "fittizio", + "fiume", + "flacone", + "flagello", + "flirtare", + "flusso", + "focaccia", + "foglio", + "fognario", + "follia", + "fonderia", + "fontana", + "forbici", + "forcella", + "foresta", + "forgiare", + "formare", + "fornace", + "foro", + "fortuna", + "forzare", + "fosforo", + "fotoni", + "fracasso", + "fragola", + "frantumi", + "fratello", + "frazione", + "freccia", + "freddo", + "frenare", + "fresco", + "friggere", + "frittata", + "frivolo", + "frizione", + "fronte", + "frullato", + "frumento", + "frusta", + "frutto", + "fucile", + "fuggire", + "fulmine", + "fumare", + "funzione", + "fuoco", + "furbizia", + "furgone", + "furia", + "furore", + "fusibile", + "fuso", + "futuro", + "gabbiano", + "galassia", + "gallina", + "gamba", + "gancio", + "garanzia", + "garofano", + "gasolio", + "gatto", + "gazebo", + "gazzetta", + "gelato", + "gemelli", + "generare", + "genitori", + "gennaio", + "geologia", + "germania", + "gestire", + "gettare", + "ghepardo", + "ghiaccio", + "giaccone", + "giaguaro", + "giallo", + "giappone", + "giardino", + "gigante", + "gioco", + "gioiello", + "giorno", + "giovane", + "giraffa", + "giudizio", + "giurare", + "giusto", + "globo", + "gloria", + "glucosio", + "gnocca", + "gocciola", + "godere", + "gomito", + "gomma", + "gonfiare", + "gorilla", + "governo", + "gradire", + "graffiti", + "granchio", + "grappolo", + "grasso", + "grattare", + "gridare", + "grissino", + "grondaia", + "grugnito", + "gruppo", + "guadagno", + "guaio", + "guancia", + "guardare", + "gufo", + "guidare", + "guscio", + "gusto", + "icona", + "idea", + "identico", + "idolo", + "idoneo", + "idrante", + "idrogeno", + "igiene", + "ignoto", + "imbarco", + "immagine", + "immobile", + "imparare", + "impedire", + "impianto", + "importo", + "impresa", + "impulso", + "incanto", + "incendio", + "incidere", + "incontro", + "incrocia", + "incubo", + "indagare", + "indice", + "indotto", + "infanzia", + "inferno", + "infinito", + "infranto", + "ingerire", + "inglese", + "ingoiare", + "ingresso", + "iniziare", + "innesco", + "insalata", + "inserire", + "insicuro", + "insonnia", + "insulto", + "interno", + "introiti", + "invasori", + "inverno", + "invito", + "invocare", + "ipnosi", + "ipocrita", + "ipotesi", + "ironia", + "irrigare", + "iscritto", + "isola", + "ispirare", + "isterico", + "istinto", + "istruire", + "italiano", + "jazz", + "labbra", + "labrador", + "ladro", + "lago", + "lamento", + "lampone", + "lancetta", + "lanterna", + "lapide", + "larva", + "lasagne", + "lasciare", + "lastra", + "latte", + "laurea", + "lavagna", + "lavorare", + "leccare", + "legare", + "leggere", + "lenzuolo", + "leone", + "lepre", + "letargo", + "lettera", + "levare", + "levitare", + "lezione", + "liberare", + "libidine", + "libro", + "licenza", + "lievito", + "limite", + "lince", + "lingua", + "liquore", + "lire", + "listino", + "litigare", + "litro", + "locale", + "lottare", + "lucciola", + "lucidare", + "luglio", + "luna", + "macchina", + "madama", + "madre", + "maestro", + "maggio", + "magico", + "maglione", + "magnolia", + "mago", + "maialino", + "maionese", + "malattia", + "male", + "malloppo", + "mancare", + "mandorla", + "mangiare", + "manico", + "manopola", + "mansarda", + "mantello", + "manubrio", + "manzo", + "mappa", + "mare", + "margine", + "marinaio", + "marmotta", + "marocco", + "martello", + "marzo", + "maschera", + "matrice", + "maturare", + "mazzetta", + "meandri", + "medaglia", + "medico", + "medusa", + "megafono", + "melone", + "membrana", + "menta", + "mercato", + "meritare", + "merluzzo", + "mese", + "mestiere", + "metafora", + "meteo", + "metodo", + "mettere", + "miele", + "miglio", + "miliardo", + "mimetica", + "minatore", + "minuto", + "miracolo", + "mirtillo", + "missile", + "mistero", + "misura", + "mito", + "mobile", + "moda", + "moderare", + "moglie", + "molecola", + "molle", + "momento", + "moneta", + "mongolia", + "monologo", + "montagna", + "morale", + "morbillo", + "mordere", + "mosaico", + "mosca", + "mostro", + "motivare", + "moto", + "mulino", + "mulo", + "muovere", + "muraglia", + "muscolo", + "museo", + "musica", + "mutande", + "nascere", + "nastro", + "natale", + "natura", + "nave", + "navigare", + "negare", + "negozio", + "nemico", + "nero", + "nervo", + "nessuno", + "nettare", + "neutroni", + "neve", + "nevicare", + "nicotina", + "nido", + "nipote", + "nocciola", + "noleggio", + "nome", + "nonno", + "norvegia", + "notare", + "notizia", + "nove", + "nucleo", + "nuda", + "nuotare", + "nutrire", + "obbligo", + "occhio", + "occupare", + "oceano", + "odissea", + "odore", + "offerta", + "officina", + "offrire", + "oggetto", + "oggi", + "olfatto", + "olio", + "oliva", + "ombelico", + "ombrello", + "omuncolo", + "ondata", + "onore", + "opera", + "opinione", + "opuscolo", + "opzione", + "orario", + "orbita", + "orchidea", + "ordine", + "orecchio", + "orgasmo", + "orgoglio", + "origine", + "orologio", + "oroscopo", + "orso", + "oscurare", + "ospedale", + "ospite", + "ossigeno", + "ostacolo", + "ostriche", + "ottenere", + "ottimo", + "ottobre", + "ovest", + "pacco", + "pace", + "pacifico", + "padella", + "pagare", + "pagina", + "pagnotta", + "palazzo", + "palestra", + "palpebre", + "pancetta", + "panfilo", + "panino", + "pannello", + "panorama", + "papa", + "paperino", + "paradiso", + "parcella", + "parente", + "parlare", + "parodia", + "parrucca", + "partire", + "passare", + "pasta", + "patata", + "patente", + "patogeno", + "patriota", + "pausa", + "pazienza", + "peccare", + "pecora", + "pedalare", + "pelare", + "pena", + "pendenza", + "penisola", + "pennello", + "pensare", + "pentirsi", + "percorso", + "perdono", + "perfetto", + "perizoma", + "perla", + "permesso", + "persona", + "pesare", + "pesce", + "peso", + "petardo", + "petrolio", + "pezzo", + "piacere", + "pianeta", + "piastra", + "piatto", + "piazza", + "piccolo", + "piede", + "piegare", + "pietra", + "pigiama", + "pigliare", + "pigrizia", + "pilastro", + "pilota", + "pinguino", + "pioggia", + "piombo", + "pionieri", + "piovra", + "pipa", + "pirata", + "pirolisi", + "piscina", + "pisolino", + "pista", + "pitone", + "piumino", + "pizza", + "plastica", + "platino", + "poesia", + "poiana", + "polaroid", + "polenta", + "polimero", + "pollo", + "polmone", + "polpetta", + "poltrona", + "pomodoro", + "pompa", + "popolo", + "porco", + "porta", + "porzione", + "possesso", + "postino", + "potassio", + "potere", + "poverino", + "pranzo", + "prato", + "prefisso", + "prelievo", + "premio", + "prendere", + "prestare", + "pretesa", + "prezzo", + "primario", + "privacy", + "problema", + "processo", + "prodotto", + "profeta", + "progetto", + "promessa", + "pronto", + "proposta", + "proroga", + "prossimo", + "proteina", + "prova", + "prudenza", + "pubblico", + "pudore", + "pugilato", + "pulire", + "pulsante", + "puntare", + "pupazzo", + "puzzle", + "quaderno", + "qualcuno", + "quarzo", + "quercia", + "quintale", + "rabbia", + "racconto", + "radice", + "raffica", + "ragazza", + "ragione", + "rammento", + "ramo", + "rana", + "randagio", + "rapace", + "rapinare", + "rapporto", + "rasatura", + "ravioli", + "reagire", + "realista", + "reattore", + "reazione", + "recitare", + "recluso", + "record", + "recupero", + "redigere", + "regalare", + "regina", + "regola", + "relatore", + "reliquia", + "remare", + "rendere", + "reparto", + "resina", + "resto", + "rete", + "retorica", + "rettile", + "revocare", + "riaprire", + "ribadire", + "ribelle", + "ricambio", + "ricetta", + "richiamo", + "ricordo", + "ridurre", + "riempire", + "riferire", + "riflesso", + "righello", + "rilancio", + "rilevare", + "rilievo", + "rimanere", + "rimborso", + "rinforzo", + "rinuncia", + "riparo", + "ripetere", + "riposare", + "ripulire", + "risalita", + "riscatto", + "riserva", + "riso", + "rispetto", + "ritaglio", + "ritmo", + "ritorno", + "ritratto", + "rituale", + "riunione", + "riuscire", + "riva", + "robotica", + "rondine", + "rosa", + "rospo", + "rosso", + "rotonda", + "rotta", + "roulotte", + "rubare", + "rubrica", + "ruffiano", + "rumore", + "ruota", + "ruscello", + "sabbia", + "sacco", + "saggio", + "sale", + "salire", + "salmone", + "salto", + "salutare", + "salvia", + "sangue", + "sanzioni", + "sapere", + "sapienza", + "sarcasmo", + "sardine", + "sartoria", + "sbalzo", + "sbarcare", + "sberla", + "sborsare", + "scadenza", + "scafo", + "scala", + "scambio", + "scappare", + "scarpa", + "scatola", + "scelta", + "scena", + "sceriffo", + "scheggia", + "schiuma", + "sciarpa", + "scienza", + "scimmia", + "sciopero", + "scivolo", + "sclerare", + "scolpire", + "sconto", + "scopa", + "scordare", + "scossa", + "scrivere", + "scrupolo", + "scuderia", + "scultore", + "scuola", + "scusare", + "sdraiare", + "secolo", + "sedativo", + "sedere", + "sedia", + "segare", + "segreto", + "seguire", + "semaforo", + "seme", + "senape", + "seno", + "sentiero", + "separare", + "sepolcro", + "sequenza", + "serata", + "serpente", + "servizio", + "sesso", + "seta", + "settore", + "sfamare", + "sfera", + "sfidare", + "sfiorare", + "sfogare", + "sgabello", + "sicuro", + "siepe", + "sigaro", + "silenzio", + "silicone", + "simbiosi", + "simpatia", + "simulare", + "sinapsi", + "sindrome", + "sinergia", + "sinonimo", + "sintonia", + "sirena", + "siringa", + "sistema", + "sito", + "smalto", + "smentire", + "smontare", + "soccorso", + "socio", + "soffitto", + "software", + "soggetto", + "sogliola", + "sognare", + "soldi", + "sole", + "sollievo", + "solo", + "sommario", + "sondare", + "sonno", + "sorpresa", + "sorriso", + "sospiro", + "sostegno", + "sovrano", + "spaccare", + "spada", + "spagnolo", + "spalla", + "sparire", + "spavento", + "spazio", + "specchio", + "spedire", + "spegnere", + "spendere", + "speranza", + "spessore", + "spezzare", + "spiaggia", + "spiccare", + "spiegare", + "spiffero", + "spingere", + "sponda", + "sporcare", + "spostare", + "spremuta", + "spugna", + "spumante", + "spuntare", + "squadra", + "squillo", + "staccare", + "stadio", + "stagione", + "stallone", + "stampa", + "stancare", + "starnuto", + "statura", + "stella", + "stendere", + "sterzo", + "stilista", + "stimolo", + "stinco", + "stiva", + "stoffa", + "storia", + "strada", + "stregone", + "striscia", + "studiare", + "stufa", + "stupendo", + "subire", + "successo", + "sudare", + "suono", + "superare", + "supporto", + "surfista", + "sussurro", + "svelto", + "svenire", + "sviluppo", + "svolta", + "svuotare", + "tabacco", + "tabella", + "tabu", + "tacchino", + "tacere", + "taglio", + "talento", + "tangente", + "tappeto", + "tartufo", + "tassello", + "tastiera", + "tavolo", + "tazza", + "teatro", + "tedesco", + "telaio", + "telefono", + "tema", + "temere", + "tempo", + "tendenza", + "tenebre", + "tensione", + "tentare", + "teologia", + "teorema", + "termica", + "terrazzo", + "teschio", + "tesi", + "tesoro", + "tessera", + "testa", + "thriller", + "tifoso", + "tigre", + "timbrare", + "timido", + "tinta", + "tirare", + "tisana", + "titano", + "titolo", + "toccare", + "togliere", + "topolino", + "torcia", + "torrente", + "tovaglia", + "traffico", + "tragitto", + "training", + "tramonto", + "transito", + "trapezio", + "trasloco", + "trattore", + "trazione", + "treccia", + "tregua", + "treno", + "triciclo", + "tridente", + "trilogia", + "tromba", + "troncare", + "trota", + "trovare", + "trucco", + "tubo", + "tulipano", + "tumulto", + "tunisia", + "tuono", + "turista", + "tuta", + "tutelare", + "tutore", + "ubriaco", + "uccello", + "udienza", + "udito", + "uffa", + "umanoide", + "umore", + "unghia", + "unguento", + "unicorno", + "unione", + "universo", + "uomo", + "uragano", + "uranio", + "urlare", + "uscire", + "utente", + "utilizzo", + "vacanza", + "vacca", + "vaglio", + "vagonata", + "valle", + "valore", + "valutare", + "valvola", + "vampiro", + "vaniglia", + "vanto", + "vapore", + "variante", + "vasca", + "vaselina", + "vassoio", + "vedere", + "vegetale", + "veglia", + "veicolo", + "vela", + "veleno", + "velivolo", + "velluto", + "vendere", + "venerare", + "venire", + "vento", + "veranda", + "verbo", + "verdura", + "vergine", + "verifica", + "vernice", + "vero", + "verruca", + "versare", + "vertebra", + "vescica", + "vespaio", + "vestito", + "vesuvio", + "veterano", + "vetro", + "vetta", + "viadotto", + "viaggio", + "vibrare", + "vicenda", + "vichingo", + "vietare", + "vigilare", + "vigneto", + "villa", + "vincere", + "violino", + "vipera", + "virgola", + "virtuoso", + "visita", + "vita", + "vitello", + "vittima", + "vivavoce", + "vivere", + "viziato", + "voglia", + "volare", + "volpe", + "volto", + "volume", + "vongole", + "voragine", + "vortice", + "votare", + "vulcano", + "vuotare", + "zabaione", + "zaffiro", + "zainetto", + "zampa", + "zanzara", + "zattera", + "zavorra", + "zenzero", + "zero", + "zingaro", + "zittire", + "zoccolo", + "zolfo", + "zombie", + "zucchero" + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/japanese.h b/src/Mnemonics/japanese.h new file mode 100644 index 0000000..4a3f3f7 --- /dev/null +++ b/src/Mnemonics/japanese.h @@ -0,0 +1,1708 @@ +// Word list originally created by dabura667 and released under The MIT License (MIT) +// +// The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Code surrounding the word list is Copyright (c) 2014-2018, The Monero Project +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file japanese.h + * + * \brief Japanese word list and map. + */ + +#ifndef JAPANESE_H +#define JAPANESE_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Japanese: public Base + { + public: + Japanese(): Base("日本語", std::vector({ + "あいこくしん", + "あいさつ", + "あいだ", + "あおぞら", + "あかちゃん", + "あきる", + "あけがた", + "あける", + "あこがれる", + "あさい", + "あさひ", + "あしあと", + "あじわう", + "あずかる", + "あずき", + "あそぶ", + "あたえる", + "あたためる", + "あたりまえ", + "あたる", + "あつい", + "あつかう", + "あっしゅく", + "あつまり", + "あつめる", + "あてな", + "あてはまる", + "あひる", + "あぶら", + "あぶる", + "あふれる", + "あまい", + "あまど", + "あまやかす", + "あまり", + "あみもの", + "あめりか", + "あやまる", + "あゆむ", + "あらいぐま", + "あらし", + "あらすじ", + "あらためる", + "あらゆる", + "あらわす", + "ありがとう", + "あわせる", + "あわてる", + "あんい", + "あんがい", + "あんこ", + "あんぜん", + "あんてい", + "あんない", + "あんまり", + "いいだす", + "いおん", + "いがい", + "いがく", + "いきおい", + "いきなり", + "いきもの", + "いきる", + "いくじ", + "いくぶん", + "いけばな", + "いけん", + "いこう", + "いこく", + "いこつ", + "いさましい", + "いさん", + "いしき", + "いじゅう", + "いじょう", + "いじわる", + "いずみ", + "いずれ", + "いせい", + "いせえび", + "いせかい", + "いせき", + "いぜん", + "いそうろう", + "いそがしい", + "いだい", + "いだく", + "いたずら", + "いたみ", + "いたりあ", + "いちおう", + "いちじ", + "いちど", + "いちば", + "いちぶ", + "いちりゅう", + "いつか", + "いっしゅん", + "いっせい", + "いっそう", + "いったん", + "いっち", + "いってい", + "いっぽう", + "いてざ", + "いてん", + "いどう", + "いとこ", + "いない", + "いなか", + "いねむり", + "いのち", + "いのる", + "いはつ", + "いばる", + "いはん", + "いびき", + "いひん", + "いふく", + "いへん", + "いほう", + "いみん", + "いもうと", + "いもたれ", + "いもり", + "いやがる", + "いやす", + "いよかん", + "いよく", + "いらい", + "いらすと", + "いりぐち", + "いりょう", + "いれい", + "いれもの", + "いれる", + "いろえんぴつ", + "いわい", + "いわう", + "いわかん", + "いわば", + "いわゆる", + "いんげんまめ", + "いんさつ", + "いんしょう", + "いんよう", + "うえき", + "うえる", + "うおざ", + "うがい", + "うかぶ", + "うかべる", + "うきわ", + "うくらいな", + "うくれれ", + "うけたまわる", + "うけつけ", + "うけとる", + "うけもつ", + "うける", + "うごかす", + "うごく", + "うこん", + "うさぎ", + "うしなう", + "うしろがみ", + "うすい", + "うすぎ", + "うすぐらい", + "うすめる", + "うせつ", + "うちあわせ", + "うちがわ", + "うちき", + "うちゅう", + "うっかり", + "うつくしい", + "うったえる", + "うつる", + "うどん", + "うなぎ", + "うなじ", + "うなずく", + "うなる", + "うねる", + "うのう", + "うぶげ", + "うぶごえ", + "うまれる", + "うめる", + "うもう", + "うやまう", + "うよく", + "うらがえす", + "うらぐち", + "うらない", + "うりあげ", + "うりきれ", + "うるさい", + "うれしい", + "うれゆき", + "うれる", + "うろこ", + "うわき", + "うわさ", + "うんこう", + "うんちん", + "うんてん", + "うんどう", + "えいえん", + "えいが", + "えいきょう", + "えいご", + "えいせい", + "えいぶん", + "えいよう", + "えいわ", + "えおり", + "えがお", + "えがく", + "えきたい", + "えくせる", + "えしゃく", + "えすて", + "えつらん", + "えのぐ", + "えほうまき", + "えほん", + "えまき", + "えもじ", + "えもの", + "えらい", + "えらぶ", + "えりあ", + "えんえん", + "えんかい", + "えんぎ", + "えんげき", + "えんしゅう", + "えんぜつ", + "えんそく", + "えんちょう", + "えんとつ", + "おいかける", + "おいこす", + "おいしい", + "おいつく", + "おうえん", + "おうさま", + "おうじ", + "おうせつ", + "おうたい", + "おうふく", + "おうべい", + "おうよう", + "おえる", + "おおい", + "おおう", + "おおどおり", + "おおや", + "おおよそ", + "おかえり", + "おかず", + "おがむ", + "おかわり", + "おぎなう", + "おきる", + "おくさま", + "おくじょう", + "おくりがな", + "おくる", + "おくれる", + "おこす", + "おこなう", + "おこる", + "おさえる", + "おさない", + "おさめる", + "おしいれ", + "おしえる", + "おじぎ", + "おじさん", + "おしゃれ", + "おそらく", + "おそわる", + "おたがい", + "おたく", + "おだやか", + "おちつく", + "おっと", + "おつり", + "おでかけ", + "おとしもの", + "おとなしい", + "おどり", + "おどろかす", + "おばさん", + "おまいり", + "おめでとう", + "おもいで", + "おもう", + "おもたい", + "おもちゃ", + "おやつ", + "おやゆび", + "およぼす", + "おらんだ", + "おろす", + "おんがく", + "おんけい", + "おんしゃ", + "おんせん", + "おんだん", + "おんちゅう", + "おんどけい", + "かあつ", + "かいが", + "がいき", + "がいけん", + "がいこう", + "かいさつ", + "かいしゃ", + "かいすいよく", + "かいぜん", + "かいぞうど", + "かいつう", + "かいてん", + "かいとう", + "かいふく", + "がいへき", + "かいほう", + "かいよう", + "がいらい", + "かいわ", + "かえる", + "かおり", + "かかえる", + "かがく", + "かがし", + "かがみ", + "かくご", + "かくとく", + "かざる", + "がぞう", + "かたい", + "かたち", + "がちょう", + "がっきゅう", + "がっこう", + "がっさん", + "がっしょう", + "かなざわし", + "かのう", + "がはく", + "かぶか", + "かほう", + "かほご", + "かまう", + "かまぼこ", + "かめれおん", + "かゆい", + "かようび", + "からい", + "かるい", + "かろう", + "かわく", + "かわら", + "がんか", + "かんけい", + "かんこう", + "かんしゃ", + "かんそう", + "かんたん", + "かんち", + "がんばる", + "きあい", + "きあつ", + "きいろ", + "ぎいん", + "きうい", + "きうん", + "きえる", + "きおう", + "きおく", + "きおち", + "きおん", + "きかい", + "きかく", + "きかんしゃ", + "ききて", + "きくばり", + "きくらげ", + "きけんせい", + "きこう", + "きこえる", + "きこく", + "きさい", + "きさく", + "きさま", + "きさらぎ", + "ぎじかがく", + "ぎしき", + "ぎじたいけん", + "ぎじにってい", + "ぎじゅつしゃ", + "きすう", + "きせい", + "きせき", + "きせつ", + "きそう", + "きぞく", + "きぞん", + "きたえる", + "きちょう", + "きつえん", + "ぎっちり", + "きつつき", + "きつね", + "きてい", + "きどう", + "きどく", + "きない", + "きなが", + "きなこ", + "きぬごし", + "きねん", + "きのう", + "きのした", + "きはく", + "きびしい", + "きひん", + "きふく", + "きぶん", + "きぼう", + "きほん", + "きまる", + "きみつ", + "きむずかしい", + "きめる", + "きもだめし", + "きもち", + "きもの", + "きゃく", + "きやく", + "ぎゅうにく", + "きよう", + "きょうりゅう", + "きらい", + "きらく", + "きりん", + "きれい", + "きれつ", + "きろく", + "ぎろん", + "きわめる", + "ぎんいろ", + "きんかくじ", + "きんじょ", + "きんようび", + "ぐあい", + "くいず", + "くうかん", + "くうき", + "くうぐん", + "くうこう", + "ぐうせい", + "くうそう", + "ぐうたら", + "くうふく", + "くうぼ", + "くかん", + "くきょう", + "くげん", + "ぐこう", + "くさい", + "くさき", + "くさばな", + "くさる", + "くしゃみ", + "くしょう", + "くすのき", + "くすりゆび", + "くせげ", + "くせん", + "ぐたいてき", + "くださる", + "くたびれる", + "くちこみ", + "くちさき", + "くつした", + "ぐっすり", + "くつろぐ", + "くとうてん", + "くどく", + "くなん", + "くねくね", + "くのう", + "くふう", + "くみあわせ", + "くみたてる", + "くめる", + "くやくしょ", + "くらす", + "くらべる", + "くるま", + "くれる", + "くろう", + "くわしい", + "ぐんかん", + "ぐんしょく", + "ぐんたい", + "ぐんて", + "けあな", + "けいかく", + "けいけん", + "けいこ", + "けいさつ", + "げいじゅつ", + "けいたい", + "げいのうじん", + "けいれき", + "けいろ", + "けおとす", + "けおりもの", + "げきか", + "げきげん", + "げきだん", + "げきちん", + "げきとつ", + "げきは", + "げきやく", + "げこう", + "げこくじょう", + "げざい", + "けさき", + "げざん", + "けしき", + "けしごむ", + "けしょう", + "げすと", + "けたば", + "けちゃっぷ", + "けちらす", + "けつあつ", + "けつい", + "けつえき", + "けっこん", + "けつじょ", + "けっせき", + "けってい", + "けつまつ", + "げつようび", + "げつれい", + "けつろん", + "げどく", + "けとばす", + "けとる", + "けなげ", + "けなす", + "けなみ", + "けぬき", + "げねつ", + "けねん", + "けはい", + "げひん", + "けぶかい", + "げぼく", + "けまり", + "けみかる", + "けむし", + "けむり", + "けもの", + "けらい", + "けろけろ", + "けわしい", + "けんい", + "けんえつ", + "けんお", + "けんか", + "げんき", + "けんげん", + "けんこう", + "けんさく", + "けんしゅう", + "けんすう", + "げんそう", + "けんちく", + "けんてい", + "けんとう", + "けんない", + "けんにん", + "げんぶつ", + "けんま", + "けんみん", + "けんめい", + "けんらん", + "けんり", + "こあくま", + "こいぬ", + "こいびと", + "ごうい", + "こうえん", + "こうおん", + "こうかん", + "ごうきゅう", + "ごうけい", + "こうこう", + "こうさい", + "こうじ", + "こうすい", + "ごうせい", + "こうそく", + "こうたい", + "こうちゃ", + "こうつう", + "こうてい", + "こうどう", + "こうない", + "こうはい", + "ごうほう", + "ごうまん", + "こうもく", + "こうりつ", + "こえる", + "こおり", + "ごかい", + "ごがつ", + "ごかん", + "こくご", + "こくさい", + "こくとう", + "こくない", + "こくはく", + "こぐま", + "こけい", + "こける", + "ここのか", + "こころ", + "こさめ", + "こしつ", + "こすう", + "こせい", + "こせき", + "こぜん", + "こそだて", + "こたい", + "こたえる", + "こたつ", + "こちょう", + "こっか", + "こつこつ", + "こつばん", + "こつぶ", + "こてい", + "こてん", + "ことがら", + "ことし", + "ことば", + "ことり", + "こなごな", + "こねこね", + "このまま", + "このみ", + "このよ", + "ごはん", + "こひつじ", + "こふう", + "こふん", + "こぼれる", + "ごまあぶら", + "こまかい", + "ごますり", + "こまつな", + "こまる", + "こむぎこ", + "こもじ", + "こもち", + "こもの", + "こもん", + "こやく", + "こやま", + "こゆう", + "こゆび", + "こよい", + "こよう", + "こりる", + "これくしょん", + "ころっけ", + "こわもて", + "こわれる", + "こんいん", + "こんかい", + "こんき", + "こんしゅう", + "こんすい", + "こんだて", + "こんとん", + "こんなん", + "こんびに", + "こんぽん", + "こんまけ", + "こんや", + "こんれい", + "こんわく", + "ざいえき", + "さいかい", + "さいきん", + "ざいげん", + "ざいこ", + "さいしょ", + "さいせい", + "ざいたく", + "ざいちゅう", + "さいてき", + "ざいりょう", + "さうな", + "さかいし", + "さがす", + "さかな", + "さかみち", + "さがる", + "さぎょう", + "さくし", + "さくひん", + "さくら", + "さこく", + "さこつ", + "さずかる", + "ざせき", + "さたん", + "さつえい", + "ざつおん", + "ざっか", + "ざつがく", + "さっきょく", + "ざっし", + "さつじん", + "ざっそう", + "さつたば", + "さつまいも", + "さてい", + "さといも", + "さとう", + "さとおや", + "さとし", + "さとる", + "さのう", + "さばく", + "さびしい", + "さべつ", + "さほう", + "さほど", + "さます", + "さみしい", + "さみだれ", + "さむけ", + "さめる", + "さやえんどう", + "さゆう", + "さよう", + "さよく", + "さらだ", + "ざるそば", + "さわやか", + "さわる", + "さんいん", + "さんか", + "さんきゃく", + "さんこう", + "さんさい", + "ざんしょ", + "さんすう", + "さんせい", + "さんそ", + "さんち", + "さんま", + "さんみ", + "さんらん", + "しあい", + "しあげ", + "しあさって", + "しあわせ", + "しいく", + "しいん", + "しうち", + "しえい", + "しおけ", + "しかい", + "しかく", + "じかん", + "しごと", + "しすう", + "じだい", + "したうけ", + "したぎ", + "したて", + "したみ", + "しちょう", + "しちりん", + "しっかり", + "しつじ", + "しつもん", + "してい", + "してき", + "してつ", + "じてん", + "じどう", + "しなぎれ", + "しなもの", + "しなん", + "しねま", + "しねん", + "しのぐ", + "しのぶ", + "しはい", + "しばかり", + "しはつ", + "しはらい", + "しはん", + "しひょう", + "しふく", + "じぶん", + "しへい", + "しほう", + "しほん", + "しまう", + "しまる", + "しみん", + "しむける", + "じむしょ", + "しめい", + "しめる", + "しもん", + "しゃいん", + "しゃうん", + "しゃおん", + "じゃがいも", + "しやくしょ", + "しゃくほう", + "しゃけん", + "しゃこ", + "しゃざい", + "しゃしん", + "しゃせん", + "しゃそう", + "しゃたい", + "しゃちょう", + "しゃっきん", + "じゃま", + "しゃりん", + "しゃれい", + "じゆう", + "じゅうしょ", + "しゅくはく", + "じゅしん", + "しゅっせき", + "しゅみ", + "しゅらば", + "じゅんばん", + "しょうかい", + "しょくたく", + "しょっけん", + "しょどう", + "しょもつ", + "しらせる", + "しらべる", + "しんか", + "しんこう", + "じんじゃ", + "しんせいじ", + "しんちく", + "しんりん", + "すあげ", + "すあし", + "すあな", + "ずあん", + "すいえい", + "すいか", + "すいとう", + "ずいぶん", + "すいようび", + "すうがく", + "すうじつ", + "すうせん", + "すおどり", + "すきま", + "すくう", + "すくない", + "すける", + "すごい", + "すこし", + "ずさん", + "すずしい", + "すすむ", + "すすめる", + "すっかり", + "ずっしり", + "ずっと", + "すてき", + "すてる", + "すねる", + "すのこ", + "すはだ", + "すばらしい", + "ずひょう", + "ずぶぬれ", + "すぶり", + "すふれ", + "すべて", + "すべる", + "ずほう", + "すぼん", + "すまい", + "すめし", + "すもう", + "すやき", + "すらすら", + "するめ", + "すれちがう", + "すろっと", + "すわる", + "すんぜん", + "すんぽう", + "せあぶら", + "せいかつ", + "せいげん", + "せいじ", + "せいよう", + "せおう", + "せかいかん", + "せきにん", + "せきむ", + "せきゆ", + "せきらんうん", + "せけん", + "せこう", + "せすじ", + "せたい", + "せたけ", + "せっかく", + "せっきゃく", + "ぜっく", + "せっけん", + "せっこつ", + "せっさたくま", + "せつぞく", + "せつだん", + "せつでん", + "せっぱん", + "せつび", + "せつぶん", + "せつめい", + "せつりつ", + "せなか", + "せのび", + "せはば", + "せびろ", + "せぼね", + "せまい", + "せまる", + "せめる", + "せもたれ", + "せりふ", + "ぜんあく", + "せんい", + "せんえい", + "せんか", + "せんきょ", + "せんく", + "せんげん", + "ぜんご", + "せんさい", + "せんしゅ", + "せんすい", + "せんせい", + "せんぞ", + "せんたく", + "せんちょう", + "せんてい", + "せんとう", + "せんぬき", + "せんねん", + "せんぱい", + "ぜんぶ", + "ぜんぽう", + "せんむ", + "せんめんじょ", + "せんもん", + "せんやく", + "せんゆう", + "せんよう", + "ぜんら", + "ぜんりゃく", + "せんれい", + "せんろ", + "そあく", + "そいとげる", + "そいね", + "そうがんきょう", + "そうき", + "そうご", + "そうしん", + "そうだん", + "そうなん", + "そうび", + "そうめん", + "そうり", + "そえもの", + "そえん", + "そがい", + "そげき", + "そこう", + "そこそこ", + "そざい", + "そしな", + "そせい", + "そせん", + "そそぐ", + "そだてる", + "そつう", + "そつえん", + "そっかん", + "そつぎょう", + "そっけつ", + "そっこう", + "そっせん", + "そっと", + "そとがわ", + "そとづら", + "そなえる", + "そなた", + "そふぼ", + "そぼく", + "そぼろ", + "そまつ", + "そまる", + "そむく", + "そむりえ", + "そめる", + "そもそも", + "そよかぜ", + "そらまめ", + "そろう", + "そんかい", + "そんけい", + "そんざい", + "そんしつ", + "そんぞく", + "そんちょう", + "ぞんび", + "ぞんぶん", + "そんみん", + "たあい", + "たいいん", + "たいうん", + "たいえき", + "たいおう", + "だいがく", + "たいき", + "たいぐう", + "たいけん", + "たいこ", + "たいざい", + "だいじょうぶ", + "だいすき", + "たいせつ", + "たいそう", + "だいたい", + "たいちょう", + "たいてい", + "だいどころ", + "たいない", + "たいねつ", + "たいのう", + "たいはん", + "だいひょう", + "たいふう", + "たいへん", + "たいほ", + "たいまつばな", + "たいみんぐ", + "たいむ", + "たいめん", + "たいやき", + "たいよう", + "たいら", + "たいりょく", + "たいる", + "たいわん", + "たうえ", + "たえる", + "たおす", + "たおる", + "たおれる", + "たかい", + "たかね", + "たきび", + "たくさん", + "たこく", + "たこやき", + "たさい", + "たしざん", + "だじゃれ", + "たすける", + "たずさわる", + "たそがれ", + "たたかう", + "たたく", + "ただしい", + "たたみ", + "たちばな", + "だっかい", + "だっきゃく", + "だっこ", + "だっしゅつ", + "だったい", + "たてる", + "たとえる", + "たなばた", + "たにん", + "たぬき", + "たのしみ", + "たはつ", + "たぶん", + "たべる", + "たぼう", + "たまご", + "たまる", + "だむる", + "ためいき", + "ためす", + "ためる", + "たもつ", + "たやすい", + "たよる", + "たらす", + "たりきほんがん", + "たりょう", + "たりる", + "たると", + "たれる", + "たれんと", + "たろっと", + "たわむれる", + "だんあつ", + "たんい", + "たんおん", + "たんか", + "たんき", + "たんけん", + "たんご", + "たんさん", + "たんじょうび", + "だんせい", + "たんそく", + "たんたい", + "だんち", + "たんてい", + "たんとう", + "だんな", + "たんにん", + "だんねつ", + "たんのう", + "たんぴん", + "だんぼう", + "たんまつ", + "たんめい", + "だんれつ", + "だんろ", + "だんわ", + "ちあい", + "ちあん", + "ちいき", + "ちいさい", + "ちえん", + "ちかい", + "ちから", + "ちきゅう", + "ちきん", + "ちけいず", + "ちけん", + "ちこく", + "ちさい", + "ちしき", + "ちしりょう", + "ちせい", + "ちそう", + "ちたい", + "ちたん", + "ちちおや", + "ちつじょ", + "ちてき", + "ちてん", + "ちぬき", + "ちぬり", + "ちのう", + "ちひょう", + "ちへいせん", + "ちほう", + "ちまた", + "ちみつ", + "ちみどろ", + "ちめいど", + "ちゃんこなべ", + "ちゅうい", + "ちゆりょく", + "ちょうし", + "ちょさくけん", + "ちらし", + "ちらみ", + "ちりがみ", + "ちりょう", + "ちるど", + "ちわわ", + "ちんたい", + "ちんもく", + "ついか", + "ついたち", + "つうか", + "つうじょう", + "つうはん", + "つうわ", + "つかう", + "つかれる", + "つくね", + "つくる", + "つけね", + "つける", + "つごう", + "つたえる", + "つづく", + "つつじ", + "つつむ", + "つとめる", + "つながる", + "つなみ", + "つねづね", + "つのる", + "つぶす", + "つまらない", + "つまる", + "つみき", + "つめたい", + "つもり", + "つもる", + "つよい", + "つるぼ", + "つるみく", + "つわもの", + "つわり", + "てあし", + "てあて", + "てあみ", + "ていおん", + "ていか", + "ていき", + "ていけい", + "ていこく", + "ていさつ", + "ていし", + "ていせい", + "ていたい", + "ていど", + "ていねい", + "ていひょう", + "ていへん", + "ていぼう", + "てうち", + "ておくれ", + "てきとう", + "てくび", + "でこぼこ", + "てさぎょう", + "てさげ", + "てすり", + "てそう", + "てちがい", + "てちょう", + "てつがく", + "てつづき", + "でっぱ", + "てつぼう", + "てつや", + "でぬかえ", + "てぬき", + "てぬぐい", + "てのひら", + "てはい", + "てぶくろ", + "てふだ", + "てほどき", + "てほん", + "てまえ", + "てまきずし", + "てみじか", + "てみやげ", + "てらす", + "てれび", + "てわけ", + "てわたし", + "でんあつ", + "てんいん", + "てんかい", + "てんき", + "てんぐ", + "てんけん", + "てんごく", + "てんさい", + "てんし", + "てんすう", + "でんち", + "てんてき", + "てんとう", + "てんない", + "てんぷら", + "てんぼうだい", + "てんめつ", + "てんらんかい", + "でんりょく", + "でんわ", + "どあい", + "といれ", + "どうかん", + "とうきゅう", + "どうぐ", + "とうし", + "とうむぎ", + "とおい", + "とおか", + "とおく", + "とおす", + "とおる", + "とかい", + "とかす", + "ときおり", + "ときどき", + "とくい", + "とくしゅう", + "とくてん", + "とくに", + "とくべつ", + "とけい", + "とける", + "とこや", + "とさか", + "としょかん", + "とそう", + "とたん", + "とちゅう", + "とっきゅう", + "とっくん", + "とつぜん", + "とつにゅう", + "とどける", + "ととのえる", + "とない", + "となえる", + "となり", + "とのさま", + "とばす", + "どぶがわ", + "とほう", + "とまる", + "とめる", + "ともだち", + "ともる", + "どようび", + "とらえる", + "とんかつ", + "どんぶり", + "ないかく", + "ないこう", + "ないしょ", + "ないす", + "ないせん", + "ないそう", + "なおす", + "ながい", + "なくす", + "なげる", + "なこうど", + "なさけ", + "なたでここ", + "なっとう", + "なつやすみ", + "ななおし", + "なにごと", + "なにもの", + "なにわ", + "なのか", + "なふだ", + "なまいき", + "なまえ", + "なまみ", + "なみだ", + "なめらか", + "なめる", + "なやむ", + "ならう", + "ならび", + "ならぶ", + "なれる", + "なわとび", + "なわばり", + "にあう", + "にいがた", + "にうけ", + "におい", + "にかい", + "にがて", + "にきび", + "にくしみ", + "にくまん", + "にげる", + "にさんかたんそ", + "にしき", + "にせもの", + "にちじょう", + "にちようび", + "にっか", + "にっき", + "にっけい", + "にっこう", + "にっさん", + "にっしょく", + "にっすう", + "にっせき", + "にってい", + "になう", + "にほん", + "にまめ", + "にもつ", + "にやり", + "にゅういん", + "にりんしゃ", + "にわとり", + "にんい", + "にんか", + "にんき", + "にんげん", + "にんしき", + "にんずう", + "にんそう", + "にんたい", + "にんち", + "にんてい", + "にんにく", + "にんぷ", + "にんまり", + "にんむ", + "にんめい", + "にんよう", + "ぬいくぎ", + "ぬかす", + "ぬぐいとる", + "ぬぐう", + "ぬくもり", + "ぬすむ", + "ぬまえび", + "ぬめり", + "ぬらす", + "ぬんちゃく", + "ねあげ", + "ねいき", + "ねいる", + "ねいろ", + "ねぐせ", + "ねくたい", + "ねくら", + "ねこぜ", + "ねこむ", + "ねさげ", + "ねすごす", + "ねそべる", + "ねだん", + "ねつい", + "ねっしん", + "ねつぞう", + "ねったいぎょ", + "ねぶそく", + "ねふだ", + "ねぼう", + "ねほりはほり", + "ねまき", + "ねまわし", + "ねみみ", + "ねむい", + "ねむたい", + "ねもと", + "ねらう", + "ねわざ", + "ねんいり", + "ねんおし", + "ねんかん", + "ねんきん", + "ねんぐ", + "ねんざ", + "ねんし", + "ねんちゃく", + "ねんど", + "ねんぴ", + "ねんぶつ", + "ねんまつ", + "ねんりょう", + "ねんれい", + "のいず", + "のおづま", + "のがす", + "のきなみ", + "のこぎり", + "のこす", + "のこる", + "のせる", + "のぞく", + "のぞむ", + "のたまう", + "のちほど", + "のっく", + "のばす", + "のはら", + "のべる", + "のぼる", + "のみもの", + "のやま", + "のらいぬ", + "のらねこ", + "のりもの", + "のりゆき", + "のれん", + "のんき", + "ばあい", + "はあく", + "ばあさん", + "ばいか", + "ばいく", + "はいけん", + "はいご", + "はいしん", + "はいすい", + "はいせん", + "はいそう", + "はいち", + "ばいばい", + "はいれつ", + "はえる", + "はおる", + "はかい", + "ばかり", + "はかる", + "はくしゅ", + "はけん", + "はこぶ", + "はさみ", + "はさん", + "はしご", + "ばしょ", + "はしる", + "はせる", + "ぱそこん", + "はそん", + "はたん", + "はちみつ", + "はつおん", + "はっかく", + "はづき", + "はっきり", + "はっくつ", + "はっけん", + "はっこう", + "はっさん", + "はっしん", + "はったつ", + "はっちゅう", + "はってん", + "はっぴょう", + "はっぽう", + "はなす", + "はなび", + "はにかむ", + "はぶらし", + "はみがき", + "はむかう", + "はめつ", + "はやい", + "はやし", + "はらう", + "はろうぃん", + "はわい", + "はんい", + "はんえい", + "はんおん", + "はんかく", + "はんきょう", + "ばんぐみ", + "はんこ", + "はんしゃ", + "はんすう", + "はんだん", + "ぱんち", + "ぱんつ", + "はんてい", + "はんとし", + "はんのう", + "はんぱ", + "はんぶん", + "はんぺん", + "はんぼうき", + "はんめい", + "はんらん", + "はんろん", + "ひいき", + "ひうん", + "ひえる", + "ひかく", + "ひかり", + "ひかる", + "ひかん", + "ひくい", + "ひけつ", + "ひこうき", + "ひこく", + "ひさい", + "ひさしぶり", + "ひさん", + "びじゅつかん", + "ひしょ" + }), 3) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/language_base.h b/src/Mnemonics/language_base.h new file mode 100644 index 0000000..959ba65 --- /dev/null +++ b/src/Mnemonics/language_base.h @@ -0,0 +1,181 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file language_base.h + * + * \brief Language Base class for Polymorphism. + */ + +#ifndef LANGUAGE_BASE_H +#define LANGUAGE_BASE_H + +#include +#include +#include +//#include "misc_log_ex.h" + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + /*! + * \brief Returns a string made of (at most) the first count characters in s. + * Assumes well formedness. No check is made for this. + * \param s The string from which to return the first count characters. + * \param count How many characters to return. + * \return A string consisting of the first count characters in s. + */ + inline std::string utf8prefix(const std::string &s, size_t count) + { + std::string prefix = ""; + const char *ptr = s.c_str(); + while (count-- && *ptr) + { + prefix += *ptr++; + while (((*ptr) & 0xc0) == 0x80) + prefix += *ptr++; + } + return prefix; + } + + /*! + * \class Base + * \brief A base language class which all languages have to inherit from for + * Polymorphism. + */ + class Base + { + protected: + enum { + ALLOW_SHORT_WORDS = 1<<0, + ALLOW_DUPLICATE_PREFIXES = 1<<1, + }; + const std::vector word_list; /*!< A pointer to the array of words */ + std::unordered_map word_map; /*!< hash table to find word's index */ + std::unordered_map trimmed_word_map; /*!< hash table to find word's trimmed index */ + std::string language_name; /*!< Name of language */ + uint32_t unique_prefix_length; /*!< Number of unique starting characters to trim the wordlist to when matching */ + /*! + * \brief Populates the word maps after the list is ready. + */ + void populate_maps(uint32_t flags = 0) + { + int ii; + std::vector::const_iterator it; + if (word_list.size () != 1626) + throw std::runtime_error("Wrong word list length for " + language_name); + for (it = word_list.begin(), ii = 0; it != word_list.end(); it++, ii++) + { + word_map[*it] = ii; + if ((*it).size() < unique_prefix_length) + { + if (flags & ALLOW_SHORT_WORDS) + { + //MWARNING(language_name << " word '" << *it << "' is shorter than its prefix length, " << unique_prefix_length); + } + else + throw std::runtime_error("Too short word in " + language_name + " word list: " + *it); + } + std::string trimmed; + if (it->length() > unique_prefix_length) + { + trimmed = utf8prefix(*it, unique_prefix_length); + } + else + { + trimmed = *it; + } + if (trimmed_word_map.find(trimmed) != trimmed_word_map.end()) + { + if (flags & ALLOW_DUPLICATE_PREFIXES) + { + //MWARNING("Duplicate prefix in " << language_name << " word list: " << trimmed); + } + else + throw std::runtime_error("Duplicate prefix in " + language_name + " word list: " + trimmed); + } + trimmed_word_map[trimmed] = ii; + } + } + public: + Base(const char *language_name, const std::vector &words, uint32_t prefix_length): + word_list(words), + unique_prefix_length(prefix_length), + language_name(language_name) + { + } + virtual ~Base() + { + } + /*! + * \brief Returns a pointer to the word list. + * \return A pointer to the word list. + */ + const std::vector& get_word_list() const + { + return word_list; + } + /*! + * \brief Returns a pointer to the word map. + * \return A pointer to the word map. + */ + const std::unordered_map& get_word_map() const + { + return word_map; + } + /*! + * \brief Returns a pointer to the trimmed word map. + * \return A pointer to the trimmed word map. + */ + const std::unordered_map& get_trimmed_word_map() const + { + return trimmed_word_map; + } + /*! + * \brief Returns the name of the language. + * \return Name of the language. + */ + const std::string &get_language_name() const + { + return language_name; + } + /*! + * \brief Returns the number of unique starting characters to be used for matching. + * \return Number of unique starting characters. + */ + uint32_t get_unique_prefix_length() const + { + return unique_prefix_length; + } + }; +} + +#endif diff --git a/src/Mnemonics/lojban.h b/src/Mnemonics/lojban.h new file mode 100644 index 0000000..213bdb6 --- /dev/null +++ b/src/Mnemonics/lojban.h @@ -0,0 +1,1693 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file lojban.h + * + * \brief New Lojban word list and map. + */ + +/* + * Word list authored by: sorpaas + * Sources: + * lo gimste jo'u lo ma'oste (http://guskant.github.io/lojbo/gismu-cmavo.html) + * N-grams of Lojban corpus (https://mw.lojban.org/papri/N-grams_of_Lojban_corpus) + */ + +#ifndef LOJBAN_H +#define LOJBAN_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Lojban: public Base + { + public: + Lojban(): Base("Lojban", std::vector({ + "backi", + "bacru", + "badna", + "badri", + "bajra", + "bakfu", + "bakni", + "bakri", + "baktu", + "balji", + "balni", + "balre", + "balvi", + "bambu", + "bancu", + "bandu", + "banfi", + "bangu", + "banli", + "banro", + "banxa", + "banzu", + "bapli", + "barda", + "bargu", + "barja", + "barna", + "bartu", + "basfa", + "basna", + "basti", + "batci", + "batke", + "bavmi", + "baxso", + "bebna", + "bekpi", + "bemro", + "bende", + "bengo", + "benji", + "benre", + "benzo", + "bergu", + "bersa", + "berti", + "besna", + "besto", + "betfu", + "betri", + "bevri", + "bidju", + "bifce", + "bikla", + "bilga", + "bilma", + "bilni", + "bindo", + "binra", + "binxo", + "birje", + "birka", + "birti", + "bisli", + "bitmu", + "bitni", + "blabi", + "blaci", + "blanu", + "bliku", + "bloti", + "bolci", + "bongu", + "boske", + "botpi", + "boxfo", + "boxna", + "bradi", + "brano", + "bratu", + "brazo", + "bredi", + "bridi", + "brife", + "briju", + "brito", + "brivo", + "broda", + "bruna", + "budjo", + "bukpu", + "bumru", + "bunda", + "bunre", + "burcu", + "burna", + "cabna", + "cabra", + "cacra", + "cadga", + "cadzu", + "cafne", + "cagna", + "cakla", + "calku", + "calse", + "canci", + "cando", + "cange", + "canja", + "canko", + "canlu", + "canpa", + "canre", + "canti", + "carce", + "carfu", + "carmi", + "carna", + "cartu", + "carvi", + "casnu", + "catke", + "catlu", + "catni", + "catra", + "caxno", + "cecla", + "cecmu", + "cedra", + "cenba", + "censa", + "centi", + "cerda", + "cerni", + "certu", + "cevni", + "cfale", + "cfari", + "cfika", + "cfila", + "cfine", + "cfipu", + "ciblu", + "cicna", + "cidja", + "cidni", + "cidro", + "cifnu", + "cigla", + "cikna", + "cikre", + "ciksi", + "cilce", + "cilfu", + "cilmo", + "cilre", + "cilta", + "cimde", + "cimni", + "cinba", + "cindu", + "cinfo", + "cinje", + "cinki", + "cinla", + "cinmo", + "cinri", + "cinse", + "cinta", + "cinza", + "cipni", + "cipra", + "cirko", + "cirla", + "ciska", + "cisma", + "cisni", + "ciste", + "citka", + "citno", + "citri", + "citsi", + "civla", + "cizra", + "ckabu", + "ckafi", + "ckaji", + "ckana", + "ckape", + "ckasu", + "ckeji", + "ckiku", + "ckilu", + "ckini", + "ckire", + "ckule", + "ckunu", + "cladu", + "clani", + "claxu", + "cletu", + "clika", + "clinu", + "clira", + "clite", + "cliva", + "clupa", + "cmaci", + "cmalu", + "cmana", + "cmavo", + "cmene", + "cmeta", + "cmevo", + "cmila", + "cmima", + "cmoni", + "cnano", + "cnebo", + "cnemu", + "cnici", + "cnino", + "cnisa", + "cnita", + "cokcu", + "condi", + "conka", + "corci", + "cortu", + "cpacu", + "cpana", + "cpare", + "cpedu", + "cpina", + "cradi", + "crane", + "creka", + "crepu", + "cribe", + "crida", + "crino", + "cripu", + "crisa", + "critu", + "ctaru", + "ctebi", + "cteki", + "ctile", + "ctino", + "ctuca", + "cukla", + "cukre", + "cukta", + "culno", + "cumki", + "cumla", + "cunmi", + "cunso", + "cuntu", + "cupra", + "curmi", + "curnu", + "curve", + "cusku", + "cusna", + "cutci", + "cutne", + "cuxna", + "dacru", + "dacti", + "dadjo", + "dakfu", + "dakli", + "damba", + "damri", + "dandu", + "danfu", + "danlu", + "danmo", + "danre", + "dansu", + "danti", + "daplu", + "dapma", + "darca", + "dargu", + "darlu", + "darno", + "darsi", + "darxi", + "daski", + "dasni", + "daspo", + "dasri", + "datka", + "datni", + "datro", + "decti", + "degji", + "dejni", + "dekpu", + "dekto", + "delno", + "dembi", + "denci", + "denmi", + "denpa", + "dertu", + "derxi", + "desku", + "detri", + "dicma", + "dicra", + "didni", + "digno", + "dikca", + "diklo", + "dikni", + "dilcu", + "dilma", + "dilnu", + "dimna", + "dindi", + "dinju", + "dinko", + "dinso", + "dirba", + "dirce", + "dirgo", + "disko", + "ditcu", + "divzi", + "dizlo", + "djacu", + "djedi", + "djica", + "djine", + "djuno", + "donri", + "dotco", + "draci", + "drani", + "drata", + "drudi", + "dugri", + "dukse", + "dukti", + "dunda", + "dunja", + "dunku", + "dunli", + "dunra", + "dutso", + "dzena", + "dzipo", + "facki", + "fadni", + "fagri", + "falnu", + "famti", + "fancu", + "fange", + "fanmo", + "fanri", + "fanta", + "fanva", + "fanza", + "fapro", + "farka", + "farlu", + "farna", + "farvi", + "fasnu", + "fatci", + "fatne", + "fatri", + "febvi", + "fegli", + "femti", + "fendi", + "fengu", + "fenki", + "fenra", + "fenso", + "fepni", + "fepri", + "ferti", + "festi", + "fetsi", + "figre", + "filso", + "finpe", + "finti", + "firca", + "fisli", + "fizbu", + "flaci", + "flalu", + "flani", + "flecu", + "flese", + "fliba", + "flira", + "foldi", + "fonmo", + "fonxa", + "forca", + "forse", + "fraso", + "frati", + "fraxu", + "frica", + "friko", + "frili", + "frinu", + "friti", + "frumu", + "fukpi", + "fulta", + "funca", + "fusra", + "fuzme", + "gacri", + "gadri", + "galfi", + "galtu", + "galxe", + "ganlo", + "ganra", + "ganse", + "ganti", + "ganxo", + "ganzu", + "gapci", + "gapru", + "garna", + "gasnu", + "gaspo", + "gasta", + "genja", + "gento", + "genxu", + "gerku", + "gerna", + "gidva", + "gigdo", + "ginka", + "girzu", + "gismu", + "glare", + "gleki", + "gletu", + "glico", + "glife", + "glosa", + "gluta", + "gocti", + "gomsi", + "gotro", + "gradu", + "grafu", + "grake", + "grana", + "grasu", + "grava", + "greku", + "grusi", + "grute", + "gubni", + "gugde", + "gugle", + "gumri", + "gundi", + "gunka", + "gunma", + "gunro", + "gunse", + "gunta", + "gurni", + "guska", + "gusni", + "gusta", + "gutci", + "gutra", + "guzme", + "jabre", + "jadni", + "jakne", + "jalge", + "jalna", + "jalra", + "jamfu", + "jamna", + "janbe", + "janco", + "janli", + "jansu", + "janta", + "jarbu", + "jarco", + "jarki", + "jaspu", + "jatna", + "javni", + "jbama", + "jbari", + "jbena", + "jbera", + "jbini", + "jdari", + "jdice", + "jdika", + "jdima", + "jdini", + "jduli", + "jecta", + "jeftu", + "jegvo", + "jelca", + "jemna", + "jenca", + "jendu", + "jenmi", + "jensi", + "jerna", + "jersi", + "jerxo", + "jesni", + "jetce", + "jetnu", + "jgalu", + "jganu", + "jgari", + "jgena", + "jgina", + "jgira", + "jgita", + "jibni", + "jibri", + "jicla", + "jicmu", + "jijnu", + "jikca", + "jikfi", + "jikni", + "jikru", + "jilka", + "jilra", + "jimca", + "jimpe", + "jimte", + "jinci", + "jinda", + "jinga", + "jinku", + "jinme", + "jinru", + "jinsa", + "jinto", + "jinvi", + "jinzi", + "jipci", + "jipno", + "jirna", + "jisra", + "jitfa", + "jitro", + "jivbu", + "jivna", + "jmaji", + "jmifa", + "jmina", + "jmive", + "jonse", + "jordo", + "jorne", + "jubme", + "judri", + "jufra", + "jukni", + "jukpa", + "julne", + "julro", + "jundi", + "jungo", + "junla", + "junri", + "junta", + "jurme", + "jursa", + "jutsi", + "juxre", + "jvinu", + "jviso", + "kabri", + "kacma", + "kadno", + "kafke", + "kagni", + "kajde", + "kajna", + "kakne", + "kakpa", + "kalci", + "kalri", + "kalsa", + "kalte", + "kamju", + "kamni", + "kampu", + "kamre", + "kanba", + "kancu", + "kandi", + "kanji", + "kanla", + "kanpe", + "kanro", + "kansa", + "kantu", + "kanxe", + "karbi", + "karce", + "karda", + "kargu", + "karli", + "karni", + "katci", + "katna", + "kavbu", + "kazra", + "kecti", + "kekli", + "kelci", + "kelvo", + "kenka", + "kenra", + "kensa", + "kerfa", + "kerlo", + "kesri", + "ketco", + "ketsu", + "kevna", + "kibro", + "kicne", + "kijno", + "kilto", + "kinda", + "kinli", + "kisto", + "klaji", + "klaku", + "klama", + "klani", + "klesi", + "kliki", + "klina", + "kliru", + "kliti", + "klupe", + "kluza", + "kobli", + "kogno", + "kojna", + "kokso", + "kolme", + "komcu", + "konju", + "korbi", + "korcu", + "korka", + "korvo", + "kosmu", + "kosta", + "krali", + "kramu", + "krasi", + "krati", + "krefu", + "krici", + "krili", + "krinu", + "krixa", + "kruca", + "kruji", + "kruvi", + "kubli", + "kucli", + "kufra", + "kukte", + "kulnu", + "kumfa", + "kumte", + "kunra", + "kunti", + "kurfa", + "kurji", + "kurki", + "kuspe", + "kusru", + "labno", + "lacni", + "lacpu", + "lacri", + "ladru", + "lafti", + "lakne", + "lakse", + "laldo", + "lalxu", + "lamji", + "lanbi", + "lanci", + "landa", + "lanka", + "lanli", + "lanme", + "lante", + "lanxe", + "lanzu", + "larcu", + "larva", + "lasna", + "lastu", + "latmo", + "latna", + "lazni", + "lebna", + "lelxe", + "lenga", + "lenjo", + "lenku", + "lerci", + "lerfu", + "libjo", + "lidne", + "lifri", + "lijda", + "limfa", + "limna", + "lince", + "lindi", + "linga", + "linji", + "linsi", + "linto", + "lisri", + "liste", + "litce", + "litki", + "litru", + "livga", + "livla", + "logji", + "loglo", + "lojbo", + "loldi", + "lorxu", + "lubno", + "lujvo", + "luksi", + "lumci", + "lunbe", + "lunra", + "lunsa", + "luska", + "lusto", + "mabla", + "mabru", + "macnu", + "majga", + "makcu", + "makfa", + "maksi", + "malsi", + "mamta", + "manci", + "manfo", + "mango", + "manku", + "manri", + "mansa", + "manti", + "mapku", + "mapni", + "mapra", + "mapti", + "marbi", + "marce", + "marde", + "margu", + "marji", + "marna", + "marxa", + "masno", + "masti", + "matci", + "matli", + "matne", + "matra", + "mavji", + "maxri", + "mebri", + "megdo", + "mekso", + "melbi", + "meljo", + "melmi", + "menli", + "menre", + "mensi", + "mentu", + "merko", + "merli", + "metfo", + "mexno", + "midju", + "mifra", + "mikce", + "mikri", + "milti", + "milxe", + "minde", + "minji", + "minli", + "minra", + "mintu", + "mipri", + "mirli", + "misno", + "misro", + "mitre", + "mixre", + "mlana", + "mlatu", + "mleca", + "mledi", + "mluni", + "mogle", + "mokca", + "moklu", + "molki", + "molro", + "morji", + "morko", + "morna", + "morsi", + "mosra", + "mraji", + "mrilu", + "mruli", + "mucti", + "mudri", + "mugle", + "mukti", + "mulno", + "munje", + "mupli", + "murse", + "murta", + "muslo", + "mutce", + "muvdu", + "muzga", + "nabmi", + "nakni", + "nalci", + "namcu", + "nanba", + "nanca", + "nandu", + "nanla", + "nanmu", + "nanvi", + "narge", + "narju", + "natfe", + "natmi", + "natsi", + "navni", + "naxle", + "nazbi", + "nejni", + "nelci", + "nenri", + "nerde", + "nibli", + "nicfa", + "nicte", + "nikle", + "nilce", + "nimre", + "ninja", + "ninmu", + "nirna", + "nitcu", + "nivji", + "nixli", + "nobli", + "norgo", + "notci", + "nudle", + "nukni", + "nunmu", + "nupre", + "nurma", + "nusna", + "nutka", + "nutli", + "nuzba", + "nuzlo", + "pacna", + "pagbu", + "pagre", + "pajni", + "palci", + "palku", + "palma", + "palne", + "palpi", + "palta", + "pambe", + "pamga", + "panci", + "pandi", + "panje", + "panka", + "panlo", + "panpi", + "panra", + "pante", + "panzi", + "papri", + "parbi", + "pardu", + "parji", + "pastu", + "patfu", + "patlu", + "patxu", + "paznu", + "pelji", + "pelxu", + "pemci", + "penbi", + "pencu", + "pendo", + "penmi", + "pensi", + "pentu", + "perli", + "pesxu", + "petso", + "pevna", + "pezli", + "picti", + "pijne", + "pikci", + "pikta", + "pilda", + "pilji", + "pilka", + "pilno", + "pimlu", + "pinca", + "pindi", + "pinfu", + "pinji", + "pinka", + "pinsi", + "pinta", + "pinxe", + "pipno", + "pixra", + "plana", + "platu", + "pleji", + "plibu", + "plini", + "plipe", + "plise", + "plita", + "plixa", + "pluja", + "pluka", + "pluta", + "pocli", + "polje", + "polno", + "ponjo", + "ponse", + "poplu", + "porpi", + "porsi", + "porto", + "prali", + "prami", + "prane", + "preja", + "prenu", + "preri", + "preti", + "prije", + "prina", + "pritu", + "proga", + "prosa", + "pruce", + "pruni", + "pruri", + "pruxi", + "pulce", + "pulji", + "pulni", + "punji", + "punli", + "pupsu", + "purci", + "purdi", + "purmo", + "racli", + "ractu", + "radno", + "rafsi", + "ragbi", + "ragve", + "rakle", + "rakso", + "raktu", + "ralci", + "ralju", + "ralte", + "randa", + "rango", + "ranji", + "ranmi", + "ransu", + "ranti", + "ranxi", + "rapli", + "rarna", + "ratcu", + "ratni", + "rebla", + "rectu", + "rekto", + "remna", + "renro", + "renvi", + "respa", + "rexsa", + "ricfu", + "rigni", + "rijno", + "rilti", + "rimni", + "rinci", + "rindo", + "rinju", + "rinka", + "rinsa", + "rirci", + "rirni", + "rirxe", + "rismi", + "risna", + "ritli", + "rivbi", + "rokci", + "romge", + "romlo", + "ronte", + "ropno", + "rorci", + "rotsu", + "rozgu", + "ruble", + "rufsu", + "runme", + "runta", + "rupnu", + "rusko", + "rutni", + "sabji", + "sabnu", + "sacki", + "saclu", + "sadjo", + "sakci", + "sakli", + "sakta", + "salci", + "salpo", + "salri", + "salta", + "samcu", + "sampu", + "sanbu", + "sance", + "sanga", + "sanji", + "sanli", + "sanmi", + "sanso", + "santa", + "sarcu", + "sarji", + "sarlu", + "sarni", + "sarxe", + "saske", + "satci", + "satre", + "savru", + "sazri", + "sefsi", + "sefta", + "sekre", + "selci", + "selfu", + "semto", + "senci", + "sengi", + "senpi", + "senta", + "senva", + "sepli", + "serti", + "sesre", + "setca", + "sevzi", + "sfani", + "sfasa", + "sfofa", + "sfubu", + "sibli", + "siclu", + "sicni", + "sicpi", + "sidbo", + "sidju", + "sigja", + "sigma", + "sikta", + "silka", + "silna", + "simlu", + "simsa", + "simxu", + "since", + "sinma", + "sinso", + "sinxa", + "sipna", + "sirji", + "sirxo", + "sisku", + "sisti", + "sitna", + "sivni", + "skaci", + "skami", + "skapi", + "skari", + "skicu", + "skiji", + "skina", + "skori", + "skoto", + "skuba", + "skuro", + "slabu", + "slaka", + "slami", + "slanu", + "slari", + "slasi", + "sligu", + "slilu", + "sliri", + "slovo", + "sluji", + "sluni", + "smacu", + "smadi", + "smaji", + "smaka", + "smani", + "smela", + "smoka", + "smuci", + "smuni", + "smusu", + "snada", + "snanu", + "snidu", + "snime", + "snipa", + "snuji", + "snura", + "snuti", + "sobde", + "sodna", + "sodva", + "softo", + "solji", + "solri", + "sombo", + "sonci", + "sorcu", + "sorgu", + "sorni", + "sorta", + "sovda", + "spaji", + "spali", + "spano", + "spati", + "speni", + "spero", + "spisa", + "spita", + "spofu", + "spoja", + "spuda", + "sputu", + "sraji", + "sraku", + "sralo", + "srana", + "srasu", + "srera", + "srito", + "sruma", + "sruri", + "stace", + "stagi", + "staku", + "stali", + "stani", + "stapa", + "stasu", + "stati", + "steba", + "steci", + "stedu", + "stela", + "stero", + "stici", + "stidi", + "stika", + "stizu", + "stodi", + "stuna", + "stura", + "stuzi", + "sucta", + "sudga", + "sufti", + "suksa", + "sumji", + "sumne", + "sumti", + "sunga", + "sunla", + "surla", + "sutra", + "tabno", + "tabra", + "tadji", + "tadni", + "tagji", + "taksi", + "talsa", + "tamca", + "tamji", + "tamne", + "tanbo", + "tance", + "tanjo", + "tanko", + "tanru", + "tansi", + "tanxe", + "tapla", + "tarbi", + "tarci", + "tarla", + "tarmi", + "tarti", + "taske", + "tasmi", + "tasta", + "tatpi", + "tatru", + "tavla", + "taxfu", + "tcaci", + "tcadu", + "tcana", + "tcati", + "tcaxe", + "tcena", + "tcese", + "tcica", + "tcidu", + "tcika", + "tcila", + "tcima", + "tcini", + "tcita", + "temci", + "temse", + "tende", + "tenfa", + "tengu", + "terdi", + "terpa", + "terto", + "tifri", + "tigni", + "tigra", + "tikpa", + "tilju", + "tinbe", + "tinci", + "tinsa", + "tirna", + "tirse", + "tirxu", + "tisna", + "titla", + "tivni", + "tixnu", + "toknu", + "toldi", + "tonga", + "tordu", + "torni", + "torso", + "traji", + "trano", + "trati", + "trene", + "tricu", + "trina", + "trixe", + "troci", + "tsaba", + "tsali", + "tsani", + "tsapi", + "tsiju", + "tsina", + "tsuku", + "tubnu", + "tubra", + "tugni", + "tujli", + "tumla", + "tunba", + "tunka", + "tunlo", + "tunta", + "tuple", + "turko", + "turni", + "tutci", + "tutle", + "tutra", + "vacri", + "vajni", + "valsi", + "vamji", + "vamtu", + "vanbi", + "vanci", + "vanju", + "vasru", + "vasxu", + "vecnu", + "vedli", + "venfu", + "vensa", + "vente", + "vepre", + "verba", + "vibna", + "vidni", + "vidru", + "vifne", + "vikmi", + "viknu", + "vimcu", + "vindu", + "vinji", + "vinta", + "vipsi", + "virnu", + "viska", + "vitci", + "vitke", + "vitno", + "vlagi", + "vlile", + "vlina", + "vlipa", + "vofli", + "voksa", + "volve", + "vorme", + "vraga", + "vreji", + "vreta", + "vrici", + "vrude", + "vrusi", + "vubla", + "vujnu", + "vukna", + "vukro", + "xabju", + "xadba", + "xadji", + "xadni", + "xagji", + "xagri", + "xajmi", + "xaksu", + "xalbo", + "xalka", + "xalni", + "xamgu", + "xampo", + "xamsi", + "xance", + "xango", + "xanka", + "xanri", + "xansa", + "xanto", + "xarci", + "xarju", + "xarnu", + "xasli", + "xasne", + "xatra", + "xatsi", + "xazdo", + "xebni", + "xebro", + "xecto", + "xedja", + "xekri", + "xelso", + "xendo", + "xenru", + "xexso", + "xigzo", + "xindo", + "xinmo", + "xirma", + "xislu", + "xispo", + "xlali", + "xlura", + "xorbo", + "xorlo", + "xotli", + "xrabo", + "xrani", + "xriso", + "xrotu", + "xruba", + "xruki", + "xrula", + "xruti", + "xukmi", + "xulta", + "xunre", + "xurdo", + "xusra", + "xutla", + "zabna", + "zajba", + "zalvi", + "zanru", + "zarci", + "zargu", + "zasni", + "zasti", + "zbabu", + "zbani", + "zbasu", + "zbepi", + "zdani", + "zdile", + "zekri", + "zenba", + "zepti", + "zetro", + "zevla", + "zgadi", + "zgana", + "zgike", + "zifre", + "zinki", + "zirpu", + "zivle", + "zmadu", + "zmiku", + "zucna", + "zukte", + "zumri", + "zungi", + "zunle", + "zunti", + "zutse", + "zvati", + "zviki", + "jbobau", + "jbopre", + "karsna", + "cabdei", + "zunsna", + "gendra", + "glibau", + "nintadni", + "pavyseljirna", + "vlaste", + "selbri", + "latro'a", + "zdakemkulgu'a", + "mriste", + "selsku", + "fu'ivla", + "tolmo'i", + "snavei", + "xagmau", + "retsku", + "ckupau", + "skudji", + "smudra", + "prulamdei", + "vokta'a", + "tinju'i", + "jefyfa'o", + "bavlamdei", + "kinzga", + "jbocre", + "jbovla", + "xauzma", + "selkei", + "xuncku", + "spusku", + "jbogu'e", + "pampe'o", + "bripre", + "jbosnu", + "zi'evla", + "gimste", + "tolzdi", + "velski", + "samselpla", + "cnegau", + "velcki", + "selja'e", + "fasybau", + "zanfri", + "reisku", + "favgau", + "jbota'a", + "rejgau", + "malgli", + "zilkai", + "keidji", + "tersu'i", + "jbofi'e", + "cnima'o", + "mulgau", + "ningau", + "ponbau", + "mrobi'o", + "rarbau", + "zmanei", + "famyma'o", + "vacysai", + "jetmlu", + "jbonunsla", + "nunpe'i", + "fa'orma'o", + "crezenzu'e", + "jbojbe", + "cmicu'a", + "zilcmi", + "tolcando", + "zukcfu", + "depybu'i", + "mencre", + "matmau", + "nunctu", + "selma'o", + "titnanba", + "naldra", + "jvajvo", + "nunsnu", + "nerkla", + "cimjvo", + "muvgau", + "zipcpi", + "runbau", + "faumlu", + "terbri", + "balcu'e", + "dragau", + "smuvelcki", + "piksku", + "selpli", + "bregau", + "zvafa'i", + "ci'izra", + "noltruti'u", + "samtci", + "snaxa'a", + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/portuguese.h b/src/Mnemonics/portuguese.h new file mode 100644 index 0000000..75a4092 --- /dev/null +++ b/src/Mnemonics/portuguese.h @@ -0,0 +1,1709 @@ +// Word list originally created by dabura667 and released under The MIT License (MIT) +// +// The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Code surrounding the word list is Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file portuguese.h + * + * \brief Portuguese word list and map. + */ + +#ifndef PORTUGUESE_H +#define PORTUGUESE_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Portuguese: public Base + { + public: + Portuguese(): Base("Português", std::vector({ + "abaular", + "abdominal", + "abeto", + "abissinio", + "abjeto", + "ablucao", + "abnegar", + "abotoar", + "abrutalhar", + "absurdo", + "abutre", + "acautelar", + "accessorios", + "acetona", + "achocolatado", + "acirrar", + "acne", + "acovardar", + "acrostico", + "actinomicete", + "acustico", + "adaptavel", + "adeus", + "adivinho", + "adjunto", + "admoestar", + "adnominal", + "adotivo", + "adquirir", + "adriatico", + "adsorcao", + "adutora", + "advogar", + "aerossol", + "afazeres", + "afetuoso", + "afixo", + "afluir", + "afortunar", + "afrouxar", + "aftosa", + "afunilar", + "agentes", + "agito", + "aglutinar", + "aiatola", + "aimore", + "aino", + "aipo", + "airoso", + "ajeitar", + "ajoelhar", + "ajudante", + "ajuste", + "alazao", + "albumina", + "alcunha", + "alegria", + "alexandre", + "alforriar", + "alguns", + "alhures", + "alivio", + "almoxarife", + "alotropico", + "alpiste", + "alquimista", + "alsaciano", + "altura", + "aluviao", + "alvura", + "amazonico", + "ambulatorio", + "ametodico", + "amizades", + "amniotico", + "amovivel", + "amurada", + "anatomico", + "ancorar", + "anexo", + "anfora", + "aniversario", + "anjo", + "anotar", + "ansioso", + "anturio", + "anuviar", + "anverso", + "anzol", + "aonde", + "apaziguar", + "apito", + "aplicavel", + "apoteotico", + "aprimorar", + "aprumo", + "apto", + "apuros", + "aquoso", + "arauto", + "arbusto", + "arduo", + "aresta", + "arfar", + "arguto", + "aritmetico", + "arlequim", + "armisticio", + "aromatizar", + "arpoar", + "arquivo", + "arrumar", + "arsenio", + "arturiano", + "aruaque", + "arvores", + "asbesto", + "ascorbico", + "aspirina", + "asqueroso", + "assustar", + "astuto", + "atazanar", + "ativo", + "atletismo", + "atmosferico", + "atormentar", + "atroz", + "aturdir", + "audivel", + "auferir", + "augusto", + "aula", + "aumento", + "aurora", + "autuar", + "avatar", + "avexar", + "avizinhar", + "avolumar", + "avulso", + "axiomatico", + "azerbaijano", + "azimute", + "azoto", + "azulejo", + "bacteriologista", + "badulaque", + "baforada", + "baixote", + "bajular", + "balzaquiana", + "bambuzal", + "banzo", + "baoba", + "baqueta", + "barulho", + "bastonete", + "batuta", + "bauxita", + "bavaro", + "bazuca", + "bcrepuscular", + "beato", + "beduino", + "begonia", + "behaviorista", + "beisebol", + "belzebu", + "bemol", + "benzido", + "beocio", + "bequer", + "berro", + "besuntar", + "betume", + "bexiga", + "bezerro", + "biatlon", + "biboca", + "bicuspide", + "bidirecional", + "bienio", + "bifurcar", + "bigorna", + "bijuteria", + "bimotor", + "binormal", + "bioxido", + "bipolarizacao", + "biquini", + "birutice", + "bisturi", + "bituca", + "biunivoco", + "bivalve", + "bizarro", + "blasfemo", + "blenorreia", + "blindar", + "bloqueio", + "blusao", + "boazuda", + "bofete", + "bojudo", + "bolso", + "bombordo", + "bonzo", + "botina", + "boquiaberto", + "bostoniano", + "botulismo", + "bourbon", + "bovino", + "boximane", + "bravura", + "brevidade", + "britar", + "broxar", + "bruno", + "bruxuleio", + "bubonico", + "bucolico", + "buda", + "budista", + "bueiro", + "buffer", + "bugre", + "bujao", + "bumerangue", + "burundines", + "busto", + "butique", + "buzios", + "caatinga", + "cabuqui", + "cacunda", + "cafuzo", + "cajueiro", + "camurca", + "canudo", + "caquizeiro", + "carvoeiro", + "casulo", + "catuaba", + "cauterizar", + "cebolinha", + "cedula", + "ceifeiro", + "celulose", + "cerzir", + "cesto", + "cetro", + "ceus", + "cevar", + "chavena", + "cheroqui", + "chita", + "chovido", + "chuvoso", + "ciatico", + "cibernetico", + "cicuta", + "cidreira", + "cientistas", + "cifrar", + "cigarro", + "cilio", + "cimo", + "cinzento", + "cioso", + "cipriota", + "cirurgico", + "cisto", + "citrico", + "ciumento", + "civismo", + "clavicula", + "clero", + "clitoris", + "cluster", + "coaxial", + "cobrir", + "cocota", + "codorniz", + "coexistir", + "cogumelo", + "coito", + "colusao", + "compaixao", + "comutativo", + "contentamento", + "convulsivo", + "coordenativa", + "coquetel", + "correto", + "corvo", + "costureiro", + "cotovia", + "covil", + "cozinheiro", + "cretino", + "cristo", + "crivo", + "crotalo", + "cruzes", + "cubo", + "cucuia", + "cueiro", + "cuidar", + "cujo", + "cultural", + "cunilingua", + "cupula", + "curvo", + "custoso", + "cutucar", + "czarismo", + "dablio", + "dacota", + "dados", + "daguerreotipo", + "daiquiri", + "daltonismo", + "damista", + "dantesco", + "daquilo", + "darwinista", + "dasein", + "dativo", + "deao", + "debutantes", + "decurso", + "deduzir", + "defunto", + "degustar", + "dejeto", + "deltoide", + "demover", + "denunciar", + "deputado", + "deque", + "dervixe", + "desvirtuar", + "deturpar", + "deuteronomio", + "devoto", + "dextrose", + "dezoito", + "diatribe", + "dicotomico", + "didatico", + "dietista", + "difuso", + "digressao", + "diluvio", + "diminuto", + "dinheiro", + "dinossauro", + "dioxido", + "diplomatico", + "dique", + "dirimivel", + "disturbio", + "diurno", + "divulgar", + "dizivel", + "doar", + "dobro", + "docura", + "dodoi", + "doer", + "dogue", + "doloso", + "domo", + "donzela", + "doping", + "dorsal", + "dossie", + "dote", + "doutro", + "doze", + "dravidico", + "dreno", + "driver", + "dropes", + "druso", + "dubnio", + "ducto", + "dueto", + "dulija", + "dundum", + "duodeno", + "duquesa", + "durou", + "duvidoso", + "duzia", + "ebano", + "ebrio", + "eburneo", + "echarpe", + "eclusa", + "ecossistema", + "ectoplasma", + "ecumenismo", + "eczema", + "eden", + "editorial", + "edredom", + "edulcorar", + "efetuar", + "efigie", + "efluvio", + "egiptologo", + "egresso", + "egua", + "einsteiniano", + "eira", + "eivar", + "eixos", + "ejetar", + "elastomero", + "eldorado", + "elixir", + "elmo", + "eloquente", + "elucidativo", + "emaranhar", + "embutir", + "emerito", + "emfa", + "emitir", + "emotivo", + "empuxo", + "emulsao", + "enamorar", + "encurvar", + "enduro", + "enevoar", + "enfurnar", + "enguico", + "enho", + "enigmista", + "enlutar", + "enormidade", + "enpreendimento", + "enquanto", + "enriquecer", + "enrugar", + "entusiastico", + "enunciar", + "envolvimento", + "enxuto", + "enzimatico", + "eolico", + "epiteto", + "epoxi", + "epura", + "equivoco", + "erario", + "erbio", + "ereto", + "erguido", + "erisipela", + "ermo", + "erotizar", + "erros", + "erupcao", + "ervilha", + "esburacar", + "escutar", + "esfuziante", + "esguio", + "esloveno", + "esmurrar", + "esoterismo", + "esperanca", + "espirito", + "espurio", + "essencialmente", + "esturricar", + "esvoacar", + "etario", + "eterno", + "etiquetar", + "etnologo", + "etos", + "etrusco", + "euclidiano", + "euforico", + "eugenico", + "eunuco", + "europio", + "eustaquio", + "eutanasia", + "evasivo", + "eventualidade", + "evitavel", + "evoluir", + "exaustor", + "excursionista", + "exercito", + "exfoliado", + "exito", + "exotico", + "expurgo", + "exsudar", + "extrusora", + "exumar", + "fabuloso", + "facultativo", + "fado", + "fagulha", + "faixas", + "fajuto", + "faltoso", + "famoso", + "fanzine", + "fapesp", + "faquir", + "fartura", + "fastio", + "faturista", + "fausto", + "favorito", + "faxineira", + "fazer", + "fealdade", + "febril", + "fecundo", + "fedorento", + "feerico", + "feixe", + "felicidade", + "felpudo", + "feltro", + "femur", + "fenotipo", + "fervura", + "festivo", + "feto", + "feudo", + "fevereiro", + "fezinha", + "fiasco", + "fibra", + "ficticio", + "fiduciario", + "fiesp", + "fifa", + "figurino", + "fijiano", + "filtro", + "finura", + "fiorde", + "fiquei", + "firula", + "fissurar", + "fitoteca", + "fivela", + "fixo", + "flavio", + "flexor", + "flibusteiro", + "flotilha", + "fluxograma", + "fobos", + "foco", + "fofura", + "foguista", + "foie", + "foliculo", + "fominha", + "fonte", + "forum", + "fosso", + "fotossintese", + "foxtrote", + "fraudulento", + "frevo", + "frivolo", + "frouxo", + "frutose", + "fuba", + "fucsia", + "fugitivo", + "fuinha", + "fujao", + "fulustreco", + "fumo", + "funileiro", + "furunculo", + "fustigar", + "futurologo", + "fuxico", + "fuzue", + "gabriel", + "gado", + "gaelico", + "gafieira", + "gaguejo", + "gaivota", + "gajo", + "galvanoplastico", + "gamo", + "ganso", + "garrucha", + "gastronomo", + "gatuno", + "gaussiano", + "gaviao", + "gaxeta", + "gazeteiro", + "gear", + "geiser", + "geminiano", + "generoso", + "genuino", + "geossinclinal", + "gerundio", + "gestual", + "getulista", + "gibi", + "gigolo", + "gilete", + "ginseng", + "giroscopio", + "glaucio", + "glacial", + "gleba", + "glifo", + "glote", + "glutonia", + "gnostico", + "goela", + "gogo", + "goitaca", + "golpista", + "gomo", + "gonzo", + "gorro", + "gostou", + "goticula", + "gourmet", + "governo", + "gozo", + "graxo", + "grevista", + "grito", + "grotesco", + "gruta", + "guaxinim", + "gude", + "gueto", + "guizo", + "guloso", + "gume", + "guru", + "gustativo", + "grelhado", + "gutural", + "habitue", + "haitiano", + "halterofilista", + "hamburguer", + "hanseniase", + "happening", + "harpista", + "hastear", + "haveres", + "hebreu", + "hectometro", + "hedonista", + "hegira", + "helena", + "helminto", + "hemorroidas", + "henrique", + "heptassilabo", + "hertziano", + "hesitar", + "heterossexual", + "heuristico", + "hexagono", + "hiato", + "hibrido", + "hidrostatico", + "hieroglifo", + "hifenizar", + "higienizar", + "hilario", + "himen", + "hino", + "hippie", + "hirsuto", + "historiografia", + "hitlerista", + "hodometro", + "hoje", + "holograma", + "homus", + "honroso", + "hoquei", + "horto", + "hostilizar", + "hotentote", + "huguenote", + "humilde", + "huno", + "hurra", + "hutu", + "iaia", + "ialorixa", + "iambico", + "iansa", + "iaque", + "iara", + "iatista", + "iberico", + "ibis", + "icar", + "iceberg", + "icosagono", + "idade", + "ideologo", + "idiotice", + "idoso", + "iemenita", + "iene", + "igarape", + "iglu", + "ignorar", + "igreja", + "iguaria", + "iidiche", + "ilativo", + "iletrado", + "ilharga", + "ilimitado", + "ilogismo", + "ilustrissimo", + "imaturo", + "imbuzeiro", + "imerso", + "imitavel", + "imovel", + "imputar", + "imutavel", + "inaveriguavel", + "incutir", + "induzir", + "inextricavel", + "infusao", + "ingua", + "inhame", + "iniquo", + "injusto", + "inning", + "inoxidavel", + "inquisitorial", + "insustentavel", + "intumescimento", + "inutilizavel", + "invulneravel", + "inzoneiro", + "iodo", + "iogurte", + "ioio", + "ionosfera", + "ioruba", + "iota", + "ipsilon", + "irascivel", + "iris", + "irlandes", + "irmaos", + "iroques", + "irrupcao", + "isca", + "isento", + "islandes", + "isotopo", + "isqueiro", + "israelita", + "isso", + "isto", + "iterbio", + "itinerario", + "itrio", + "iuane", + "iugoslavo", + "jabuticabeira", + "jacutinga", + "jade", + "jagunco", + "jainista", + "jaleco", + "jambo", + "jantarada", + "japones", + "jaqueta", + "jarro", + "jasmim", + "jato", + "jaula", + "javel", + "jazz", + "jegue", + "jeitoso", + "jejum", + "jenipapo", + "jeova", + "jequitiba", + "jersei", + "jesus", + "jetom", + "jiboia", + "jihad", + "jilo", + "jingle", + "jipe", + "jocoso", + "joelho", + "joguete", + "joio", + "jojoba", + "jorro", + "jota", + "joule", + "joviano", + "jubiloso", + "judoca", + "jugular", + "juizo", + "jujuba", + "juliano", + "jumento", + "junto", + "jururu", + "justo", + "juta", + "juventude", + "labutar", + "laguna", + "laico", + "lajota", + "lanterninha", + "lapso", + "laquear", + "lastro", + "lauto", + "lavrar", + "laxativo", + "lazer", + "leasing", + "lebre", + "lecionar", + "ledo", + "leguminoso", + "leitura", + "lele", + "lemure", + "lento", + "leonardo", + "leopardo", + "lepton", + "leque", + "leste", + "letreiro", + "leucocito", + "levitico", + "lexicologo", + "lhama", + "lhufas", + "liame", + "licoroso", + "lidocaina", + "liliputiano", + "limusine", + "linotipo", + "lipoproteina", + "liquidos", + "lirismo", + "lisura", + "liturgico", + "livros", + "lixo", + "lobulo", + "locutor", + "lodo", + "logro", + "lojista", + "lombriga", + "lontra", + "loop", + "loquaz", + "lorota", + "losango", + "lotus", + "louvor", + "luar", + "lubrificavel", + "lucros", + "lugubre", + "luis", + "luminoso", + "luneta", + "lustroso", + "luto", + "luvas", + "luxuriante", + "luzeiro", + "maduro", + "maestro", + "mafioso", + "magro", + "maiuscula", + "majoritario", + "malvisto", + "mamute", + "manutencao", + "mapoteca", + "maquinista", + "marzipa", + "masturbar", + "matuto", + "mausoleu", + "mavioso", + "maxixe", + "mazurca", + "meandro", + "mecha", + "medusa", + "mefistofelico", + "megera", + "meirinho", + "melro", + "memorizar", + "menu", + "mequetrefe", + "mertiolate", + "mestria", + "metroviario", + "mexilhao", + "mezanino", + "miau", + "microssegundo", + "midia", + "migratorio", + "mimosa", + "minuto", + "miosotis", + "mirtilo", + "misturar", + "mitzvah", + "miudos", + "mixuruca", + "mnemonico", + "moagem", + "mobilizar", + "modulo", + "moer", + "mofo", + "mogno", + "moita", + "molusco", + "monumento", + "moqueca", + "morubixaba", + "mostruario", + "motriz", + "mouse", + "movivel", + "mozarela", + "muarra", + "muculmano", + "mudo", + "mugir", + "muitos", + "mumunha", + "munir", + "muon", + "muquira", + "murros", + "musselina", + "nacoes", + "nado", + "naftalina", + "nago", + "naipe", + "naja", + "nalgum", + "namoro", + "nanquim", + "napolitano", + "naquilo", + "nascimento", + "nautilo", + "navios", + "nazista", + "nebuloso", + "nectarina", + "nefrologo", + "negus", + "nelore", + "nenufar", + "nepotismo", + "nervura", + "neste", + "netuno", + "neutron", + "nevoeiro", + "newtoniano", + "nexo", + "nhenhenhem", + "nhoque", + "nigeriano", + "niilista", + "ninho", + "niobio", + "niponico", + "niquelar", + "nirvana", + "nisto", + "nitroglicerina", + "nivoso", + "nobreza", + "nocivo", + "noel", + "nogueira", + "noivo", + "nojo", + "nominativo", + "nonuplo", + "noruegues", + "nostalgico", + "noturno", + "nouveau", + "nuanca", + "nublar", + "nucleotideo", + "nudista", + "nulo", + "numismatico", + "nunquinha", + "nupcias", + "nutritivo", + "nuvens", + "oasis", + "obcecar", + "obeso", + "obituario", + "objetos", + "oblongo", + "obnoxio", + "obrigatorio", + "obstruir", + "obtuso", + "obus", + "obvio", + "ocaso", + "occipital", + "oceanografo", + "ocioso", + "oclusivo", + "ocorrer", + "ocre", + "octogono", + "odalisca", + "odisseia", + "odorifico", + "oersted", + "oeste", + "ofertar", + "ofidio", + "oftalmologo", + "ogiva", + "ogum", + "oigale", + "oitavo", + "oitocentos", + "ojeriza", + "olaria", + "oleoso", + "olfato", + "olhos", + "oliveira", + "olmo", + "olor", + "olvidavel", + "ombudsman", + "omeleteira", + "omitir", + "omoplata", + "onanismo", + "ondular", + "oneroso", + "onomatopeico", + "ontologico", + "onus", + "onze", + "opalescente", + "opcional", + "operistico", + "opio", + "oposto", + "oprobrio", + "optometrista", + "opusculo", + "oratorio", + "orbital", + "orcar", + "orfao", + "orixa", + "orla", + "ornitologo", + "orquidea", + "ortorrombico", + "orvalho", + "osculo", + "osmotico", + "ossudo", + "ostrogodo", + "otario", + "otite", + "ouro", + "ousar", + "outubro", + "ouvir", + "ovario", + "overnight", + "oviparo", + "ovni", + "ovoviviparo", + "ovulo", + "oxala", + "oxente", + "oxiuro", + "oxossi", + "ozonizar", + "paciente", + "pactuar", + "padronizar", + "paete", + "pagodeiro", + "paixao", + "pajem", + "paludismo", + "pampas", + "panturrilha", + "papudo", + "paquistanes", + "pastoso", + "patua", + "paulo", + "pauzinhos", + "pavoroso", + "paxa", + "pazes", + "peao", + "pecuniario", + "pedunculo", + "pegaso", + "peixinho", + "pejorativo", + "pelvis", + "penuria", + "pequno", + "petunia", + "pezada", + "piauiense", + "pictorico", + "pierro", + "pigmeu", + "pijama", + "pilulas", + "pimpolho", + "pintura", + "piorar", + "pipocar", + "piqueteiro", + "pirulito", + "pistoleiro", + "pituitaria", + "pivotar", + "pixote", + "pizzaria", + "plistoceno", + "plotar", + "pluviometrico", + "pneumonico", + "poco", + "podridao", + "poetisa", + "pogrom", + "pois", + "polvorosa", + "pomposo", + "ponderado", + "pontudo", + "populoso", + "poquer", + "porvir", + "posudo", + "potro", + "pouso", + "povoar", + "prazo", + "prezar", + "privilegios", + "proximo", + "prussiano", + "pseudopode", + "psoriase", + "pterossauros", + "ptialina", + "ptolemaico", + "pudor", + "pueril", + "pufe", + "pugilista", + "puir", + "pujante", + "pulverizar", + "pumba", + "punk", + "purulento", + "pustula", + "putsch", + "puxe", + "quatrocentos", + "quetzal", + "quixotesco", + "quotizavel", + "rabujice", + "racista", + "radonio", + "rafia", + "ragu", + "rajado", + "ralo", + "rampeiro", + "ranzinza", + "raptor", + "raquitismo", + "raro", + "rasurar", + "ratoeira", + "ravioli", + "razoavel", + "reavivar", + "rebuscar", + "recusavel", + "reduzivel", + "reexposicao", + "refutavel", + "regurgitar", + "reivindicavel", + "rejuvenescimento", + "relva", + "remuneravel", + "renunciar", + "reorientar", + "repuxo", + "requisito", + "resumo", + "returno", + "reutilizar", + "revolvido", + "rezonear", + "riacho", + "ribossomo", + "ricota", + "ridiculo", + "rifle", + "rigoroso", + "rijo", + "rimel", + "rins", + "rios", + "riqueza", + "respeito", + "rissole", + "ritualistico", + "rivalizar", + "rixa", + "robusto", + "rococo", + "rodoviario", + "roer", + "rogo", + "rojao", + "rolo", + "rompimento", + "ronronar", + "roqueiro", + "rorqual", + "rosto", + "rotundo", + "rouxinol", + "roxo", + "royal", + "ruas", + "rucula", + "rudimentos", + "ruela", + "rufo", + "rugoso", + "ruivo", + "rule", + "rumoroso", + "runico", + "ruptura", + "rural", + "rustico", + "rutilar", + "saariano", + "sabujo", + "sacudir", + "sadomasoquista", + "safra", + "sagui", + "sais", + "samurai", + "santuario", + "sapo", + "saquear", + "sartriano", + "saturno", + "saude", + "sauva", + "saveiro", + "saxofonista", + "sazonal", + "scherzo", + "script", + "seara", + "seborreia", + "secura", + "seduzir", + "sefardim", + "seguro", + "seja", + "selvas", + "sempre", + "senzala", + "sepultura", + "sequoia", + "sestercio", + "setuplo", + "seus", + "seviciar", + "sezonismo", + "shalom", + "siames", + "sibilante", + "sicrano", + "sidra", + "sifilitico", + "signos", + "silvo", + "simultaneo", + "sinusite", + "sionista", + "sirio", + "sisudo", + "situar", + "sivan", + "slide", + "slogan", + "soar", + "sobrio", + "socratico", + "sodomizar", + "soerguer", + "software", + "sogro", + "soja", + "solver", + "somente", + "sonso", + "sopro", + "soquete", + "sorveteiro", + "sossego", + "soturno", + "sousafone", + "sovinice", + "sozinho", + "suavizar", + "subverter", + "sucursal", + "sudoriparo", + "sufragio", + "sugestoes", + "suite", + "sujo", + "sultao", + "sumula", + "suntuoso", + "suor", + "supurar", + "suruba", + "susto", + "suturar", + "suvenir", + "tabuleta", + "taco", + "tadjique", + "tafeta", + "tagarelice", + "taitiano", + "talvez", + "tampouco", + "tanzaniano", + "taoista", + "tapume", + "taquion", + "tarugo", + "tascar", + "tatuar", + "tautologico", + "tavola", + "taxionomista", + "tchecoslovaco", + "teatrologo", + "tectonismo", + "tedioso", + "teflon", + "tegumento", + "teixo", + "telurio", + "temporas", + "tenue", + "teosofico", + "tepido", + "tequila", + "terrorista", + "testosterona", + "tetrico", + "teutonico", + "teve", + "texugo", + "tiara", + "tibia", + "tiete", + "tifoide", + "tigresa", + "tijolo", + "tilintar", + "timpano", + "tintureiro", + "tiquete", + "tiroteio", + "tisico", + "titulos", + "tive", + "toar", + "toboga", + "tofu", + "togoles", + "toicinho", + "tolueno", + "tomografo", + "tontura", + "toponimo", + "toquio", + "torvelinho", + "tostar", + "toto", + "touro", + "toxina", + "trazer", + "trezentos", + "trivialidade", + "trovoar", + "truta", + "tuaregue", + "tubular", + "tucano", + "tudo", + "tufo", + "tuiste", + "tulipa", + "tumultuoso", + "tunisino", + "tupiniquim", + "turvo", + "tutu", + "ucraniano", + "udenista", + "ufanista", + "ufologo", + "ugaritico", + "uiste", + "uivo", + "ulceroso", + "ulema", + "ultravioleta", + "umbilical", + "umero", + "umido", + "umlaut", + "unanimidade", + "unesco", + "ungulado", + "unheiro", + "univoco", + "untuoso", + "urano", + "urbano", + "urdir", + "uretra", + "urgente", + "urinol", + "urna", + "urologo", + "urro", + "ursulina", + "urtiga", + "urupe", + "usavel", + "usbeque", + "usei", + "usineiro", + "usurpar", + "utero", + "utilizar", + "utopico", + "uvular", + "uxoricidio", + "vacuo", + "vadio", + "vaguear", + "vaivem", + "valvula", + "vampiro", + "vantajoso", + "vaporoso", + "vaquinha", + "varziano", + "vasto", + "vaticinio", + "vaudeville", + "vazio", + "veado", + "vedico", + "veemente", + "vegetativo", + "veio", + "veja", + "veludo", + "venusiano", + "verdade", + "verve", + "vestuario", + "vetusto", + "vexatorio", + "vezes", + "viavel", + "vibratorio", + "victor", + "vicunha", + "vidros", + "vietnamita", + "vigoroso", + "vilipendiar", + "vime", + "vintem", + "violoncelo", + "viquingue", + "virus", + "visualizar", + "vituperio", + "viuvo", + "vivo", + "vizir", + "voar", + "vociferar", + "vodu", + "vogar", + "voile", + "volver", + "vomito", + "vontade", + "vortice", + "vosso", + "voto", + "vovozinha", + "voyeuse", + "vozes", + "vulva", + "vupt", + "western", + "xadrez", + "xale", + "xampu", + "xango", + "xarope", + "xaual", + "xavante", + "xaxim", + "xenonio", + "xepa", + "xerox", + "xicara", + "xifopago", + "xiita", + "xilogravura", + "xinxim", + "xistoso", + "xixi", + "xodo", + "xogum", + "xucro", + "zabumba", + "zagueiro", + "zambiano", + "zanzar", + "zarpar", + "zebu", + "zefiro", + "zeloso", + "zenite", + "zumbi" + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/russian.h b/src/Mnemonics/russian.h new file mode 100644 index 0000000..e36b7bb --- /dev/null +++ b/src/Mnemonics/russian.h @@ -0,0 +1,1688 @@ +// Word list created by Monero contributor sammy007 +// +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file russian.h + * + * \brief Russian word list and map. + */ + +#ifndef RUSSIAN_H +#define RUSSIAN_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Russian: public Base + { + public: + Russian(): Base("русский язык", std::vector({ + "абажур", + "абзац", + "абонент", + "абрикос", + "абсурд", + "авангард", + "август", + "авиация", + "авоська", + "автор", + "агат", + "агент", + "агитатор", + "агнец", + "агония", + "агрегат", + "адвокат", + "адмирал", + "адрес", + "ажиотаж", + "азарт", + "азбука", + "азот", + "аист", + "айсберг", + "академия", + "аквариум", + "аккорд", + "акробат", + "аксиома", + "актер", + "акула", + "акция", + "алгоритм", + "алебарда", + "аллея", + "алмаз", + "алтарь", + "алфавит", + "алхимик", + "алый", + "альбом", + "алюминий", + "амбар", + "аметист", + "амнезия", + "ампула", + "амфора", + "анализ", + "ангел", + "анекдот", + "анимация", + "анкета", + "аномалия", + "ансамбль", + "антенна", + "апатия", + "апельсин", + "апофеоз", + "аппарат", + "апрель", + "аптека", + "арабский", + "арбуз", + "аргумент", + "арест", + "ария", + "арка", + "армия", + "аромат", + "арсенал", + "артист", + "архив", + "аршин", + "асбест", + "аскетизм", + "аспект", + "ассорти", + "астроном", + "асфальт", + "атака", + "ателье", + "атлас", + "атом", + "атрибут", + "аудитор", + "аукцион", + "аура", + "афера", + "афиша", + "ахинея", + "ацетон", + "аэропорт", + "бабушка", + "багаж", + "бадья", + "база", + "баклажан", + "балкон", + "бампер", + "банк", + "барон", + "бассейн", + "батарея", + "бахрома", + "башня", + "баян", + "бегство", + "бедро", + "бездна", + "бекон", + "белый", + "бензин", + "берег", + "беседа", + "бетонный", + "биатлон", + "библия", + "бивень", + "бигуди", + "бидон", + "бизнес", + "бикини", + "билет", + "бинокль", + "биология", + "биржа", + "бисер", + "битва", + "бицепс", + "благо", + "бледный", + "близкий", + "блок", + "блуждать", + "блюдо", + "бляха", + "бобер", + "богатый", + "бодрый", + "боевой", + "бокал", + "большой", + "борьба", + "босой", + "ботинок", + "боцман", + "бочка", + "боярин", + "брать", + "бревно", + "бригада", + "бросать", + "брызги", + "брюки", + "бублик", + "бугор", + "будущее", + "буква", + "бульвар", + "бумага", + "бунт", + "бурный", + "бусы", + "бутылка", + "буфет", + "бухта", + "бушлат", + "бывалый", + "быль", + "быстрый", + "быть", + "бюджет", + "бюро", + "бюст", + "вагон", + "важный", + "ваза", + "вакцина", + "валюта", + "вампир", + "ванная", + "вариант", + "вассал", + "вата", + "вафля", + "вахта", + "вдова", + "вдыхать", + "ведущий", + "веер", + "вежливый", + "везти", + "веко", + "великий", + "вена", + "верить", + "веселый", + "ветер", + "вечер", + "вешать", + "вещь", + "веяние", + "взаимный", + "взбучка", + "взвод", + "взгляд", + "вздыхать", + "взлетать", + "взмах", + "взнос", + "взор", + "взрыв", + "взывать", + "взятка", + "вибрация", + "визит", + "вилка", + "вино", + "вирус", + "висеть", + "витрина", + "вихрь", + "вишневый", + "включать", + "вкус", + "власть", + "влечь", + "влияние", + "влюблять", + "внешний", + "внимание", + "внук", + "внятный", + "вода", + "воевать", + "вождь", + "воздух", + "войти", + "вокзал", + "волос", + "вопрос", + "ворота", + "восток", + "впадать", + "впускать", + "врач", + "время", + "вручать", + "всадник", + "всеобщий", + "вспышка", + "встреча", + "вторник", + "вулкан", + "вурдалак", + "входить", + "въезд", + "выбор", + "вывод", + "выгодный", + "выделять", + "выезжать", + "выживать", + "вызывать", + "выигрыш", + "вылезать", + "выносить", + "выпивать", + "высокий", + "выходить", + "вычет", + "вышка", + "выяснять", + "вязать", + "вялый", + "гавань", + "гадать", + "газета", + "гаишник", + "галстук", + "гамма", + "гарантия", + "гастроли", + "гвардия", + "гвоздь", + "гектар", + "гель", + "генерал", + "геолог", + "герой", + "гешефт", + "гибель", + "гигант", + "гильза", + "гимн", + "гипотеза", + "гитара", + "глаз", + "глина", + "глоток", + "глубокий", + "глыба", + "глядеть", + "гнать", + "гнев", + "гнить", + "гном", + "гнуть", + "говорить", + "годовой", + "голова", + "гонка", + "город", + "гость", + "готовый", + "граница", + "грех", + "гриб", + "громкий", + "группа", + "грызть", + "грязный", + "губа", + "гудеть", + "гулять", + "гуманный", + "густой", + "гуща", + "давать", + "далекий", + "дама", + "данные", + "дарить", + "дать", + "дача", + "дверь", + "движение", + "двор", + "дебют", + "девушка", + "дедушка", + "дежурный", + "дезертир", + "действие", + "декабрь", + "дело", + "демократ", + "день", + "депутат", + "держать", + "десяток", + "детский", + "дефицит", + "дешевый", + "деятель", + "джаз", + "джинсы", + "джунгли", + "диалог", + "диван", + "диета", + "дизайн", + "дикий", + "динамика", + "диплом", + "директор", + "диск", + "дитя", + "дичь", + "длинный", + "дневник", + "добрый", + "доверие", + "договор", + "дождь", + "доза", + "документ", + "должен", + "домашний", + "допрос", + "дорога", + "доход", + "доцент", + "дочь", + "дощатый", + "драка", + "древний", + "дрожать", + "друг", + "дрянь", + "дубовый", + "дуга", + "дудка", + "дукат", + "дуло", + "думать", + "дупло", + "дурак", + "дуть", + "духи", + "душа", + "дуэт", + "дымить", + "дыня", + "дыра", + "дыханье", + "дышать", + "дьявол", + "дюжина", + "дюйм", + "дюна", + "дядя", + "дятел", + "егерь", + "единый", + "едкий", + "ежевика", + "ежик", + "езда", + "елка", + "емкость", + "ерунда", + "ехать", + "жадный", + "жажда", + "жалеть", + "жанр", + "жара", + "жать", + "жгучий", + "ждать", + "жевать", + "желание", + "жемчуг", + "женщина", + "жертва", + "жесткий", + "жечь", + "живой", + "жидкость", + "жизнь", + "жилье", + "жирный", + "житель", + "журнал", + "жюри", + "забывать", + "завод", + "загадка", + "задача", + "зажечь", + "зайти", + "закон", + "замечать", + "занимать", + "западный", + "зарплата", + "засыпать", + "затрата", + "захват", + "зацепка", + "зачет", + "защита", + "заявка", + "звать", + "звезда", + "звонить", + "звук", + "здание", + "здешний", + "здоровье", + "зебра", + "зевать", + "зеленый", + "земля", + "зенит", + "зеркало", + "зефир", + "зигзаг", + "зима", + "зиять", + "злак", + "злой", + "змея", + "знать", + "зной", + "зодчий", + "золотой", + "зомби", + "зона", + "зоопарк", + "зоркий", + "зрачок", + "зрение", + "зритель", + "зубной", + "зыбкий", + "зять", + "игла", + "иголка", + "играть", + "идея", + "идиот", + "идол", + "идти", + "иерархия", + "избрать", + "известие", + "изгонять", + "издание", + "излагать", + "изменять", + "износ", + "изоляция", + "изрядный", + "изучать", + "изымать", + "изящный", + "икона", + "икра", + "иллюзия", + "имбирь", + "иметь", + "имидж", + "иммунный", + "империя", + "инвестор", + "индивид", + "инерция", + "инженер", + "иномарка", + "институт", + "интерес", + "инфекция", + "инцидент", + "ипподром", + "ирис", + "ирония", + "искать", + "история", + "исходить", + "исчезать", + "итог", + "июль", + "июнь", + "кабинет", + "кавалер", + "кадр", + "казарма", + "кайф", + "кактус", + "калитка", + "камень", + "канал", + "капитан", + "картина", + "касса", + "катер", + "кафе", + "качество", + "каша", + "каюта", + "квартира", + "квинтет", + "квота", + "кедр", + "кекс", + "кенгуру", + "кепка", + "керосин", + "кетчуп", + "кефир", + "кибитка", + "кивнуть", + "кидать", + "километр", + "кино", + "киоск", + "кипеть", + "кирпич", + "кисть", + "китаец", + "класс", + "клетка", + "клиент", + "клоун", + "клуб", + "клык", + "ключ", + "клятва", + "книга", + "кнопка", + "кнут", + "князь", + "кобура", + "ковер", + "коготь", + "кодекс", + "кожа", + "козел", + "койка", + "коктейль", + "колено", + "компания", + "конец", + "копейка", + "короткий", + "костюм", + "котел", + "кофе", + "кошка", + "красный", + "кресло", + "кричать", + "кровь", + "крупный", + "крыша", + "крючок", + "кубок", + "кувшин", + "кудрявый", + "кузов", + "кукла", + "культура", + "кумир", + "купить", + "курс", + "кусок", + "кухня", + "куча", + "кушать", + "кювет", + "лабиринт", + "лавка", + "лагерь", + "ладонь", + "лазерный", + "лайнер", + "лакей", + "лампа", + "ландшафт", + "лапа", + "ларек", + "ласковый", + "лауреат", + "лачуга", + "лаять", + "лгать", + "лебедь", + "левый", + "легкий", + "ледяной", + "лежать", + "лекция", + "лента", + "лепесток", + "лесной", + "лето", + "лечь", + "леший", + "лживый", + "либерал", + "ливень", + "лига", + "лидер", + "ликовать", + "лиловый", + "лимон", + "линия", + "липа", + "лирика", + "лист", + "литр", + "лифт", + "лихой", + "лицо", + "личный", + "лишний", + "лобовой", + "ловить", + "логика", + "лодка", + "ложка", + "лозунг", + "локоть", + "ломать", + "лоно", + "лопата", + "лорд", + "лось", + "лоток", + "лохматый", + "лошадь", + "лужа", + "лукавый", + "луна", + "лупить", + "лучший", + "лыжный", + "лысый", + "львиный", + "льгота", + "льдина", + "любить", + "людской", + "люстра", + "лютый", + "лягушка", + "магазин", + "мадам", + "мазать", + "майор", + "максимум", + "мальчик", + "манера", + "март", + "масса", + "мать", + "мафия", + "махать", + "мачта", + "машина", + "маэстро", + "маяк", + "мгла", + "мебель", + "медведь", + "мелкий", + "мемуары", + "менять", + "мера", + "место", + "метод", + "механизм", + "мечтать", + "мешать", + "миграция", + "мизинец", + "микрофон", + "миллион", + "минута", + "мировой", + "миссия", + "митинг", + "мишень", + "младший", + "мнение", + "мнимый", + "могила", + "модель", + "мозг", + "мойка", + "мокрый", + "молодой", + "момент", + "монах", + "море", + "мост", + "мотор", + "мохнатый", + "мочь", + "мошенник", + "мощный", + "мрачный", + "мстить", + "мудрый", + "мужчина", + "музыка", + "мука", + "мумия", + "мундир", + "муравей", + "мусор", + "мутный", + "муфта", + "муха", + "мучить", + "мушкетер", + "мыло", + "мысль", + "мыть", + "мычать", + "мышь", + "мэтр", + "мюзикл", + "мягкий", + "мякиш", + "мясо", + "мятый", + "мячик", + "набор", + "навык", + "нагрузка", + "надежда", + "наемный", + "нажать", + "называть", + "наивный", + "накрыть", + "налог", + "намерен", + "наносить", + "написать", + "народ", + "натура", + "наука", + "нация", + "начать", + "небо", + "невеста", + "негодяй", + "неделя", + "нежный", + "незнание", + "нелепый", + "немалый", + "неправда", + "нервный", + "нести", + "нефть", + "нехватка", + "нечистый", + "неясный", + "нива", + "нижний", + "низкий", + "никель", + "нирвана", + "нить", + "ничья", + "ниша", + "нищий", + "новый", + "нога", + "ножницы", + "ноздря", + "ноль", + "номер", + "норма", + "нота", + "ночь", + "ноша", + "ноябрь", + "нрав", + "нужный", + "нутро", + "нынешний", + "нырнуть", + "ныть", + "нюанс", + "нюхать", + "няня", + "оазис", + "обаяние", + "обвинять", + "обгонять", + "обещать", + "обжигать", + "обзор", + "обида", + "область", + "обмен", + "обнимать", + "оборона", + "образ", + "обучение", + "обходить", + "обширный", + "общий", + "объект", + "обычный", + "обязать", + "овальный", + "овес", + "овощи", + "овраг", + "овца", + "овчарка", + "огненный", + "огонь", + "огромный", + "огурец", + "одежда", + "одинокий", + "одобрить", + "ожидать", + "ожог", + "озарение", + "озеро", + "означать", + "оказать", + "океан", + "оклад", + "окно", + "округ", + "октябрь", + "окурок", + "олень", + "опасный", + "операция", + "описать", + "оплата", + "опора", + "оппонент", + "опрос", + "оптимизм", + "опускать", + "опыт", + "орать", + "орбита", + "орган", + "орден", + "орел", + "оригинал", + "оркестр", + "орнамент", + "оружие", + "осадок", + "освещать", + "осень", + "осина", + "осколок", + "осмотр", + "основной", + "особый", + "осуждать", + "отбор", + "отвечать", + "отдать", + "отец", + "отзыв", + "открытие", + "отмечать", + "относить", + "отпуск", + "отрасль", + "отставка", + "оттенок", + "отходить", + "отчет", + "отъезд", + "офицер", + "охапка", + "охота", + "охрана", + "оценка", + "очаг", + "очередь", + "очищать", + "очки", + "ошейник", + "ошибка", + "ощущение", + "павильон", + "падать", + "паек", + "пакет", + "палец", + "память", + "панель", + "папка", + "партия", + "паспорт", + "патрон", + "пауза", + "пафос", + "пахнуть", + "пациент", + "пачка", + "пашня", + "певец", + "педагог", + "пейзаж", + "пельмень", + "пенсия", + "пепел", + "период", + "песня", + "петля", + "пехота", + "печать", + "пешеход", + "пещера", + "пианист", + "пиво", + "пиджак", + "пиковый", + "пилот", + "пионер", + "пирог", + "писать", + "пить", + "пицца", + "пишущий", + "пища", + "план", + "плечо", + "плита", + "плохой", + "плыть", + "плюс", + "пляж", + "победа", + "повод", + "погода", + "подумать", + "поехать", + "пожимать", + "позиция", + "поиск", + "покой", + "получать", + "помнить", + "пони", + "поощрять", + "попадать", + "порядок", + "пост", + "поток", + "похожий", + "поцелуй", + "почва", + "пощечина", + "поэт", + "пояснить", + "право", + "предмет", + "проблема", + "пруд", + "прыгать", + "прямой", + "психолог", + "птица", + "публика", + "пугать", + "пудра", + "пузырь", + "пуля", + "пункт", + "пурга", + "пустой", + "путь", + "пухлый", + "пучок", + "пушистый", + "пчела", + "пшеница", + "пыль", + "пытка", + "пыхтеть", + "пышный", + "пьеса", + "пьяный", + "пятно", + "работа", + "равный", + "радость", + "развитие", + "район", + "ракета", + "рамка", + "ранний", + "рапорт", + "рассказ", + "раунд", + "рация", + "рвать", + "реальный", + "ребенок", + "реветь", + "регион", + "редакция", + "реестр", + "режим", + "резкий", + "рейтинг", + "река", + "религия", + "ремонт", + "рента", + "реплика", + "ресурс", + "реформа", + "рецепт", + "речь", + "решение", + "ржавый", + "рисунок", + "ритм", + "рифма", + "робкий", + "ровный", + "рогатый", + "родитель", + "рождение", + "розовый", + "роковой", + "роль", + "роман", + "ронять", + "рост", + "рота", + "роща", + "рояль", + "рубль", + "ругать", + "руда", + "ружье", + "руины", + "рука", + "руль", + "румяный", + "русский", + "ручка", + "рыба", + "рывок", + "рыдать", + "рыжий", + "рынок", + "рысь", + "рыть", + "рыхлый", + "рыцарь", + "рычаг", + "рюкзак", + "рюмка", + "рябой", + "рядовой", + "сабля", + "садовый", + "сажать", + "салон", + "самолет", + "сани", + "сапог", + "сарай", + "сатира", + "сауна", + "сахар", + "сбегать", + "сбивать", + "сбор", + "сбыт", + "свадьба", + "свет", + "свидание", + "свобода", + "связь", + "сгорать", + "сдвигать", + "сеанс", + "северный", + "сегмент", + "седой", + "сезон", + "сейф", + "секунда", + "сельский", + "семья", + "сентябрь", + "сердце", + "сеть", + "сечение", + "сеять", + "сигнал", + "сидеть", + "сизый", + "сила", + "символ", + "синий", + "сирота", + "система", + "ситуация", + "сиять", + "сказать", + "скважина", + "скелет", + "скидка", + "склад", + "скорый", + "скрывать", + "скучный", + "слава", + "слеза", + "слияние", + "слово", + "случай", + "слышать", + "слюна", + "смех", + "смирение", + "смотреть", + "смутный", + "смысл", + "смятение", + "снаряд", + "снег", + "снижение", + "сносить", + "снять", + "событие", + "совет", + "согласие", + "сожалеть", + "сойти", + "сокол", + "солнце", + "сомнение", + "сонный", + "сообщать", + "соперник", + "сорт", + "состав", + "сотня", + "соус", + "социолог", + "сочинять", + "союз", + "спать", + "спешить", + "спина", + "сплошной", + "способ", + "спутник", + "средство", + "срок", + "срывать", + "стать", + "ствол", + "стена", + "стихи", + "сторона", + "страна", + "студент", + "стыд", + "субъект", + "сувенир", + "сугроб", + "судьба", + "суета", + "суждение", + "сукно", + "сулить", + "сумма", + "сунуть", + "супруг", + "суровый", + "сустав", + "суть", + "сухой", + "суша", + "существо", + "сфера", + "схема", + "сцена", + "счастье", + "счет", + "считать", + "сшивать", + "съезд", + "сынок", + "сыпать", + "сырье", + "сытый", + "сыщик", + "сюжет", + "сюрприз", + "таблица", + "таежный", + "таинство", + "тайна", + "такси", + "талант", + "таможня", + "танец", + "тарелка", + "таскать", + "тахта", + "тачка", + "таять", + "тварь", + "твердый", + "творить", + "театр", + "тезис", + "текст", + "тело", + "тема", + "тень", + "теория", + "теплый", + "терять", + "тесный", + "тетя", + "техника", + "течение", + "тигр", + "типичный", + "тираж", + "титул", + "тихий", + "тишина", + "ткань", + "товарищ", + "толпа", + "тонкий", + "топливо", + "торговля", + "тоска", + "точка", + "тощий", + "традиция", + "тревога", + "трибуна", + "трогать", + "труд", + "трюк", + "тряпка", + "туалет", + "тугой", + "туловище", + "туман", + "тундра", + "тупой", + "турнир", + "тусклый", + "туфля", + "туча", + "туша", + "тыкать", + "тысяча", + "тьма", + "тюльпан", + "тюрьма", + "тяга", + "тяжелый", + "тянуть", + "убеждать", + "убирать", + "убогий", + "убыток", + "уважение", + "уверять", + "увлекать", + "угнать", + "угол", + "угроза", + "удар", + "удивлять", + "удобный", + "уезд", + "ужас", + "ужин", + "узел", + "узкий", + "узнавать", + "узор", + "уйма", + "уклон", + "укол", + "уксус", + "улетать", + "улица", + "улучшать", + "улыбка", + "уметь", + "умиление", + "умный", + "умолять", + "умысел", + "унижать", + "уносить", + "уныние", + "упасть", + "уплата", + "упор", + "упрекать", + "упускать", + "уран", + "урна", + "уровень", + "усадьба", + "усердие", + "усилие", + "ускорять", + "условие", + "усмешка", + "уснуть", + "успеть", + "усыпать", + "утешать", + "утка", + "уточнять", + "утро", + "утюг", + "уходить", + "уцелеть", + "участие", + "ученый", + "учитель", + "ушко", + "ущерб", + "уютный", + "уяснять", + "фабрика", + "фаворит", + "фаза", + "файл", + "факт", + "фамилия", + "фантазия", + "фара", + "фасад", + "февраль", + "фельдшер", + "феномен", + "ферма", + "фигура", + "физика", + "фильм", + "финал", + "фирма", + "фишка", + "флаг", + "флейта", + "флот", + "фокус", + "фольклор", + "фонд", + "форма", + "фото", + "фраза", + "фреска", + "фронт", + "фрукт", + "функция", + "фуражка", + "футбол", + "фыркать", + "халат", + "хамство", + "хаос", + "характер", + "хата", + "хватать", + "хвост", + "хижина", + "хилый", + "химия", + "хирург", + "хитрый", + "хищник", + "хлам", + "хлеб", + "хлопать", + "хмурый", + "ходить", + "хозяин", + "хоккей", + "холодный", + "хороший", + "хотеть", + "хохотать", + "храм", + "хрен", + "хриплый", + "хроника", + "хрупкий", + "художник", + "хулиган", + "хутор", + "царь", + "цвет", + "цель", + "цемент", + "центр", + "цепь", + "церковь", + "цикл", + "цилиндр", + "циничный", + "цирк", + "цистерна", + "цитата", + "цифра", + "цыпленок", + "чадо", + "чайник", + "часть", + "чашка", + "человек", + "чемодан", + "чепуха", + "черный", + "честь", + "четкий", + "чехол", + "чиновник", + "число", + "читать", + "членство", + "чреватый", + "чтение", + "чувство", + "чугунный", + "чудо", + "чужой", + "чукча", + "чулок", + "чума", + "чуткий", + "чучело", + "чушь", + "шаблон", + "шагать", + "шайка", + "шакал", + "шалаш", + "шампунь", + "шанс", + "шапка", + "шарик", + "шасси", + "шатер", + "шахта", + "шашлык", + "швейный", + "швырять", + "шевелить", + "шедевр", + "шейка", + "шелковый", + "шептать", + "шерсть", + "шестерка", + "шикарный", + "шинель", + "шипеть", + "широкий", + "шить", + "шишка", + "шкаф", + "школа", + "шкура", + "шланг", + "шлем", + "шлюпка", + "шляпа", + "шнур", + "шоколад", + "шорох", + "шоссе", + "шофер", + "шпага", + "шпион", + "шприц", + "шрам", + "шрифт", + "штаб", + "штора", + "штраф", + "штука", + "штык", + "шуба", + "шуметь", + "шуршать", + "шутка", + "щадить", + "щедрый", + "щека", + "щель", + "щенок", + "щепка", + "щетка", + "щука", + "эволюция", + "эгоизм", + "экзамен", + "экипаж", + "экономия", + "экран", + "эксперт", + "элемент", + "элита", + "эмблема", + "эмигрант", + "эмоция", + "энергия", + "эпизод", + "эпоха", + "эскиз", + "эссе", + "эстрада", + "этап", + "этика", + "этюд", + "эфир", + "эффект", + "эшелон", + "юбилей", + "юбка", + "южный", + "юмор", + "юноша", + "юрист", + "яблоко", + "явление", + "ягода", + "ядерный", + "ядовитый", + "ядро", + "язва", + "язык", + "яйцо", + "якорь", + "январь", + "японец", + "яркий", + "ярмарка", + "ярость", + "ярус", + "ясный", + "яхта", + "ячейка", + "ящик" + }), 4) + { + populate_maps(); + } + }; +} + +#endif diff --git a/src/Mnemonics/singleton.h b/src/Mnemonics/singleton.h new file mode 100644 index 0000000..b7c7de2 --- /dev/null +++ b/src/Mnemonics/singleton.h @@ -0,0 +1,62 @@ +// Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file singleton.h + * + * \brief A singleton helper class based on template. + */ + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + /*! + * \class Singleton + * + * \brief Single helper class. + * + * Do Language::Singleton::instance() to create a singleton instance + * of `YourClass`. + */ + template + class Singleton + { + Singleton() {} + Singleton(Singleton &s) {} + Singleton& operator=(const Singleton&) {} + public: + static T* instance() + { + static T* obj = new T; + return obj; + } + }; +} diff --git a/src/Mnemonics/spanish.h b/src/Mnemonics/spanish.h new file mode 100644 index 0000000..5f38dbb --- /dev/null +++ b/src/Mnemonics/spanish.h @@ -0,0 +1,1709 @@ +// Word list originally created by dabura667 and released under The MIT License (MIT) +// +// The MIT License (MIT) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Code surrounding the word list is Copyright (c) 2014-2018, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/*! + * \file spanish.h + * + * \brief Spanish word list and map. + */ + +#ifndef SPANISH_H +#define SPANISH_H + +#include +#include +#include "language_base.h" +#include + +/*! + * \namespace Language + * \brief Mnemonic language related namespace. + */ +namespace Language +{ + class Spanish: public Base + { + public: + Spanish(): Base("Español", std::vector({ + "ábaco", + "abdomen", + "abeja", + "abierto", + "abogado", + "abono", + "aborto", + "abrazo", + "abrir", + "abuelo", + "abuso", + "acabar", + "academia", + "acceso", + "acción", + "aceite", + "acelga", + "acento", + "aceptar", + "ácido", + "aclarar", + "acné", + "acoger", + "acoso", + "activo", + "acto", + "actriz", + "actuar", + "acudir", + "acuerdo", + "acusar", + "adicto", + "admitir", + "adoptar", + "adorno", + "aduana", + "adulto", + "aéreo", + "afectar", + "afición", + "afinar", + "afirmar", + "ágil", + "agitar", + "agonía", + "agosto", + "agotar", + "agregar", + "agrio", + "agua", + "agudo", + "águila", + "aguja", + "ahogo", + "ahorro", + "aire", + "aislar", + "ajedrez", + "ajeno", + "ajuste", + "alacrán", + "alambre", + "alarma", + "alba", + "álbum", + "alcalde", + "aldea", + "alegre", + "alejar", + "alerta", + "aleta", + "alfiler", + "alga", + "algodón", + "aliado", + "aliento", + "alivio", + "alma", + "almeja", + "almíbar", + "altar", + "alteza", + "altivo", + "alto", + "altura", + "alumno", + "alzar", + "amable", + "amante", + "amapola", + "amargo", + "amasar", + "ámbar", + "ámbito", + "ameno", + "amigo", + "amistad", + "amor", + "amparo", + "amplio", + "ancho", + "anciano", + "ancla", + "andar", + "andén", + "anemia", + "ángulo", + "anillo", + "ánimo", + "anís", + "anotar", + "antena", + "antiguo", + "antojo", + "anual", + "anular", + "anuncio", + "añadir", + "añejo", + "año", + "apagar", + "aparato", + "apetito", + "apio", + "aplicar", + "apodo", + "aporte", + "apoyo", + "aprender", + "aprobar", + "apuesta", + "apuro", + "arado", + "araña", + "arar", + "árbitro", + "árbol", + "arbusto", + "archivo", + "arco", + "arder", + "ardilla", + "arduo", + "área", + "árido", + "aries", + "armonía", + "arnés", + "aroma", + "arpa", + "arpón", + "arreglo", + "arroz", + "arruga", + "arte", + "artista", + "asa", + "asado", + "asalto", + "ascenso", + "asegurar", + "aseo", + "asesor", + "asiento", + "asilo", + "asistir", + "asno", + "asombro", + "áspero", + "astilla", + "astro", + "astuto", + "asumir", + "asunto", + "atajo", + "ataque", + "atar", + "atento", + "ateo", + "ático", + "atleta", + "átomo", + "atraer", + "atroz", + "atún", + "audaz", + "audio", + "auge", + "aula", + "aumento", + "ausente", + "autor", + "aval", + "avance", + "avaro", + "ave", + "avellana", + "avena", + "avestruz", + "avión", + "aviso", + "ayer", + "ayuda", + "ayuno", + "azafrán", + "azar", + "azote", + "azúcar", + "azufre", + "azul", + "baba", + "babor", + "bache", + "bahía", + "baile", + "bajar", + "balanza", + "balcón", + "balde", + "bambú", + "banco", + "banda", + "baño", + "barba", + "barco", + "barniz", + "barro", + "báscula", + "bastón", + "basura", + "batalla", + "batería", + "batir", + "batuta", + "baúl", + "bazar", + "bebé", + "bebida", + "bello", + "besar", + "beso", + "bestia", + "bicho", + "bien", + "bingo", + "blanco", + "bloque", + "blusa", + "boa", + "bobina", + "bobo", + "boca", + "bocina", + "boda", + "bodega", + "boina", + "bola", + "bolero", + "bolsa", + "bomba", + "bondad", + "bonito", + "bono", + "bonsái", + "borde", + "borrar", + "bosque", + "bote", + "botín", + "bóveda", + "bozal", + "bravo", + "brazo", + "brecha", + "breve", + "brillo", + "brinco", + "brisa", + "broca", + "broma", + "bronce", + "brote", + "bruja", + "brusco", + "bruto", + "buceo", + "bucle", + "bueno", + "buey", + "bufanda", + "bufón", + "búho", + "buitre", + "bulto", + "burbuja", + "burla", + "burro", + "buscar", + "butaca", + "buzón", + "caballo", + "cabeza", + "cabina", + "cabra", + "cacao", + "cadáver", + "cadena", + "caer", + "café", + "caída", + "caimán", + "caja", + "cajón", + "cal", + "calamar", + "calcio", + "caldo", + "calidad", + "calle", + "calma", + "calor", + "calvo", + "cama", + "cambio", + "camello", + "camino", + "campo", + "cáncer", + "candil", + "canela", + "canguro", + "canica", + "canto", + "caña", + "cañón", + "caoba", + "caos", + "capaz", + "capitán", + "capote", + "captar", + "capucha", + "cara", + "carbón", + "cárcel", + "careta", + "carga", + "cariño", + "carne", + "carpeta", + "carro", + "carta", + "casa", + "casco", + "casero", + "caspa", + "castor", + "catorce", + "catre", + "caudal", + "causa", + "cazo", + "cebolla", + "ceder", + "cedro", + "celda", + "célebre", + "celoso", + "célula", + "cemento", + "ceniza", + "centro", + "cerca", + "cerdo", + "cereza", + "cero", + "cerrar", + "certeza", + "césped", + "cetro", + "chacal", + "chaleco", + "champú", + "chancla", + "chapa", + "charla", + "chico", + "chiste", + "chivo", + "choque", + "choza", + "chuleta", + "chupar", + "ciclón", + "ciego", + "cielo", + "cien", + "cierto", + "cifra", + "cigarro", + "cima", + "cinco", + "cine", + "cinta", + "ciprés", + "circo", + "ciruela", + "cisne", + "cita", + "ciudad", + "clamor", + "clan", + "claro", + "clase", + "clave", + "cliente", + "clima", + "clínica", + "cobre", + "cocción", + "cochino", + "cocina", + "coco", + "código", + "codo", + "cofre", + "coger", + "cohete", + "cojín", + "cojo", + "cola", + "colcha", + "colegio", + "colgar", + "colina", + "collar", + "colmo", + "columna", + "combate", + "comer", + "comida", + "cómodo", + "compra", + "conde", + "conejo", + "conga", + "conocer", + "consejo", + "contar", + "copa", + "copia", + "corazón", + "corbata", + "corcho", + "cordón", + "corona", + "correr", + "coser", + "cosmos", + "costa", + "cráneo", + "cráter", + "crear", + "crecer", + "creído", + "crema", + "cría", + "crimen", + "cripta", + "crisis", + "cromo", + "crónica", + "croqueta", + "crudo", + "cruz", + "cuadro", + "cuarto", + "cuatro", + "cubo", + "cubrir", + "cuchara", + "cuello", + "cuento", + "cuerda", + "cuesta", + "cueva", + "cuidar", + "culebra", + "culpa", + "culto", + "cumbre", + "cumplir", + "cuna", + "cuneta", + "cuota", + "cupón", + "cúpula", + "curar", + "curioso", + "curso", + "curva", + "cutis", + "dama", + "danza", + "dar", + "dardo", + "dátil", + "deber", + "débil", + "década", + "decir", + "dedo", + "defensa", + "definir", + "dejar", + "delfín", + "delgado", + "delito", + "demora", + "denso", + "dental", + "deporte", + "derecho", + "derrota", + "desayuno", + "deseo", + "desfile", + "desnudo", + "destino", + "desvío", + "detalle", + "detener", + "deuda", + "día", + "diablo", + "diadema", + "diamante", + "diana", + "diario", + "dibujo", + "dictar", + "diente", + "dieta", + "diez", + "difícil", + "digno", + "dilema", + "diluir", + "dinero", + "directo", + "dirigir", + "disco", + "diseño", + "disfraz", + "diva", + "divino", + "doble", + "doce", + "dolor", + "domingo", + "don", + "donar", + "dorado", + "dormir", + "dorso", + "dos", + "dosis", + "dragón", + "droga", + "ducha", + "duda", + "duelo", + "dueño", + "dulce", + "dúo", + "duque", + "durar", + "dureza", + "duro", + "ébano", + "ebrio", + "echar", + "eco", + "ecuador", + "edad", + "edición", + "edificio", + "editor", + "educar", + "efecto", + "eficaz", + "eje", + "ejemplo", + "elefante", + "elegir", + "elemento", + "elevar", + "elipse", + "élite", + "elixir", + "elogio", + "eludir", + "embudo", + "emitir", + "emoción", + "empate", + "empeño", + "empleo", + "empresa", + "enano", + "encargo", + "enchufe", + "encía", + "enemigo", + "enero", + "enfado", + "enfermo", + "engaño", + "enigma", + "enlace", + "enorme", + "enredo", + "ensayo", + "enseñar", + "entero", + "entrar", + "envase", + "envío", + "época", + "equipo", + "erizo", + "escala", + "escena", + "escolar", + "escribir", + "escudo", + "esencia", + "esfera", + "esfuerzo", + "espada", + "espejo", + "espía", + "esposa", + "espuma", + "esquí", + "estar", + "este", + "estilo", + "estufa", + "etapa", + "eterno", + "ética", + "etnia", + "evadir", + "evaluar", + "evento", + "evitar", + "exacto", + "examen", + "exceso", + "excusa", + "exento", + "exigir", + "exilio", + "existir", + "éxito", + "experto", + "explicar", + "exponer", + "extremo", + "fábrica", + "fábula", + "fachada", + "fácil", + "factor", + "faena", + "faja", + "falda", + "fallo", + "falso", + "faltar", + "fama", + "familia", + "famoso", + "faraón", + "farmacia", + "farol", + "farsa", + "fase", + "fatiga", + "fauna", + "favor", + "fax", + "febrero", + "fecha", + "feliz", + "feo", + "feria", + "feroz", + "fértil", + "fervor", + "festín", + "fiable", + "fianza", + "fiar", + "fibra", + "ficción", + "ficha", + "fideo", + "fiebre", + "fiel", + "fiera", + "fiesta", + "figura", + "fijar", + "fijo", + "fila", + "filete", + "filial", + "filtro", + "fin", + "finca", + "fingir", + "finito", + "firma", + "flaco", + "flauta", + "flecha", + "flor", + "flota", + "fluir", + "flujo", + "flúor", + "fobia", + "foca", + "fogata", + "fogón", + "folio", + "folleto", + "fondo", + "forma", + "forro", + "fortuna", + "forzar", + "fosa", + "foto", + "fracaso", + "frágil", + "franja", + "frase", + "fraude", + "freír", + "freno", + "fresa", + "frío", + "frito", + "fruta", + "fuego", + "fuente", + "fuerza", + "fuga", + "fumar", + "función", + "funda", + "furgón", + "furia", + "fusil", + "fútbol", + "futuro", + "gacela", + "gafas", + "gaita", + "gajo", + "gala", + "galería", + "gallo", + "gamba", + "ganar", + "gancho", + "ganga", + "ganso", + "garaje", + "garza", + "gasolina", + "gastar", + "gato", + "gavilán", + "gemelo", + "gemir", + "gen", + "género", + "genio", + "gente", + "geranio", + "gerente", + "germen", + "gesto", + "gigante", + "gimnasio", + "girar", + "giro", + "glaciar", + "globo", + "gloria", + "gol", + "golfo", + "goloso", + "golpe", + "goma", + "gordo", + "gorila", + "gorra", + "gota", + "goteo", + "gozar", + "grada", + "gráfico", + "grano", + "grasa", + "gratis", + "grave", + "grieta", + "grillo", + "gripe", + "gris", + "grito", + "grosor", + "grúa", + "grueso", + "grumo", + "grupo", + "guante", + "guapo", + "guardia", + "guerra", + "guía", + "guiño", + "guion", + "guiso", + "guitarra", + "gusano", + "gustar", + "haber", + "hábil", + "hablar", + "hacer", + "hacha", + "hada", + "hallar", + "hamaca", + "harina", + "haz", + "hazaña", + "hebilla", + "hebra", + "hecho", + "helado", + "helio", + "hembra", + "herir", + "hermano", + "héroe", + "hervir", + "hielo", + "hierro", + "hígado", + "higiene", + "hijo", + "himno", + "historia", + "hocico", + "hogar", + "hoguera", + "hoja", + "hombre", + "hongo", + "honor", + "honra", + "hora", + "hormiga", + "horno", + "hostil", + "hoyo", + "hueco", + "huelga", + "huerta", + "hueso", + "huevo", + "huida", + "huir", + "humano", + "húmedo", + "humilde", + "humo", + "hundir", + "huracán", + "hurto", + "icono", + "ideal", + "idioma", + "ídolo", + "iglesia", + "iglú", + "igual", + "ilegal", + "ilusión", + "imagen", + "imán", + "imitar", + "impar", + "imperio", + "imponer", + "impulso", + "incapaz", + "índice", + "inerte", + "infiel", + "informe", + "ingenio", + "inicio", + "inmenso", + "inmune", + "innato", + "insecto", + "instante", + "interés", + "íntimo", + "intuir", + "inútil", + "invierno", + "ira", + "iris", + "ironía", + "isla", + "islote", + "jabalí", + "jabón", + "jamón", + "jarabe", + "jardín", + "jarra", + "jaula", + "jazmín", + "jefe", + "jeringa", + "jinete", + "jornada", + "joroba", + "joven", + "joya", + "juerga", + "jueves", + "juez", + "jugador", + "jugo", + "juguete", + "juicio", + "junco", + "jungla", + "junio", + "juntar", + "júpiter", + "jurar", + "justo", + "juvenil", + "juzgar", + "kilo", + "koala", + "labio", + "lacio", + "lacra", + "lado", + "ladrón", + "lagarto", + "lágrima", + "laguna", + "laico", + "lamer", + "lámina", + "lámpara", + "lana", + "lancha", + "langosta", + "lanza", + "lápiz", + "largo", + "larva", + "lástima", + "lata", + "látex", + "latir", + "laurel", + "lavar", + "lazo", + "leal", + "lección", + "leche", + "lector", + "leer", + "legión", + "legumbre", + "lejano", + "lengua", + "lento", + "leña", + "león", + "leopardo", + "lesión", + "letal", + "letra", + "leve", + "leyenda", + "libertad", + "libro", + "licor", + "líder", + "lidiar", + "lienzo", + "liga", + "ligero", + "lima", + "límite", + "limón", + "limpio", + "lince", + "lindo", + "línea", + "lingote", + "lino", + "linterna", + "líquido", + "liso", + "lista", + "litera", + "litio", + "litro", + "llaga", + "llama", + "llanto", + "llave", + "llegar", + "llenar", + "llevar", + "llorar", + "llover", + "lluvia", + "lobo", + "loción", + "loco", + "locura", + "lógica", + "logro", + "lombriz", + "lomo", + "lonja", + "lote", + "lucha", + "lucir", + "lugar", + "lujo", + "luna", + "lunes", + "lupa", + "lustro", + "luto", + "luz", + "maceta", + "macho", + "madera", + "madre", + "maduro", + "maestro", + "mafia", + "magia", + "mago", + "maíz", + "maldad", + "maleta", + "malla", + "malo", + "mamá", + "mambo", + "mamut", + "manco", + "mando", + "manejar", + "manga", + "maniquí", + "manjar", + "mano", + "manso", + "manta", + "mañana", + "mapa", + "máquina", + "mar", + "marco", + "marea", + "marfil", + "margen", + "marido", + "mármol", + "marrón", + "martes", + "marzo", + "masa", + "máscara", + "masivo", + "matar", + "materia", + "matiz", + "matriz", + "máximo", + "mayor", + "mazorca", + "mecha", + "medalla", + "medio", + "médula", + "mejilla", + "mejor", + "melena", + "melón", + "memoria", + "menor", + "mensaje", + "mente", + "menú", + "mercado", + "merengue", + "mérito", + "mes", + "mesón", + "meta", + "meter", + "método", + "metro", + "mezcla", + "miedo", + "miel", + "miembro", + "miga", + "mil", + "milagro", + "militar", + "millón", + "mimo", + "mina", + "minero", + "mínimo", + "minuto", + "miope", + "mirar", + "misa", + "miseria", + "misil", + "mismo", + "mitad", + "mito", + "mochila", + "moción", + "moda", + "modelo", + "moho", + "mojar", + "molde", + "moler", + "molino", + "momento", + "momia", + "monarca", + "moneda", + "monja", + "monto", + "moño", + "morada", + "morder", + "moreno", + "morir", + "morro", + "morsa", + "mortal", + "mosca", + "mostrar", + "motivo", + "mover", + "móvil", + "mozo", + "mucho", + "mudar", + "mueble", + "muela", + "muerte", + "muestra", + "mugre", + "mujer", + "mula", + "muleta", + "multa", + "mundo", + "muñeca", + "mural", + "muro", + "músculo", + "museo", + "musgo", + "música", + "muslo", + "nácar", + "nación", + "nadar", + "naipe", + "naranja", + "nariz", + "narrar", + "nasal", + "natal", + "nativo", + "natural", + "náusea", + "naval", + "nave", + "navidad", + "necio", + "néctar", + "negar", + "negocio", + "negro", + "neón", + "nervio", + "neto", + "neutro", + "nevar", + "nevera", + "nicho", + "nido", + "niebla", + "nieto", + "niñez", + "niño", + "nítido", + "nivel", + "nobleza", + "noche", + "nómina", + "noria", + "norma", + "norte", + "nota", + "noticia", + "novato", + "novela", + "novio", + "nube", + "nuca", + "núcleo", + "nudillo", + "nudo", + "nuera", + "nueve", + "nuez", + "nulo", + "número", + "nutria", + "oasis", + "obeso", + "obispo", + "objeto", + "obra", + "obrero", + "observar", + "obtener", + "obvio", + "oca", + "ocaso", + "océano", + "ochenta", + "ocho", + "ocio", + "ocre", + "octavo", + "octubre", + "oculto", + "ocupar", + "ocurrir", + "odiar", + "odio", + "odisea", + "oeste", + "ofensa", + "oferta", + "oficio", + "ofrecer", + "ogro", + "oído", + "oír", + "ojo", + "ola", + "oleada", + "olfato", + "olivo", + "olla", + "olmo", + "olor", + "olvido", + "ombligo", + "onda", + "onza", + "opaco", + "opción", + "ópera", + "opinar", + "oponer", + "optar", + "óptica", + "opuesto", + "oración", + "orador", + "oral", + "órbita", + "orca", + "orden", + "oreja", + "órgano", + "orgía", + "orgullo", + "oriente", + "origen", + "orilla", + "oro", + "orquesta", + "oruga", + "osadía", + "oscuro", + "osezno", + "oso", + "ostra", + "otoño", + "otro", + "oveja", + "óvulo", + "óxido", + "oxígeno", + "oyente", + "ozono", + "pacto", + "padre", + "paella", + "página", + "pago", + "país", + "pájaro", + "palabra", + "palco", + "paleta", + "pálido", + "palma", + "paloma", + "palpar", + "pan", + "panal", + "pánico", + "pantera", + "pañuelo", + "papá", + "papel", + "papilla", + "paquete", + "parar", + "parcela", + "pared", + "parir", + "paro", + "párpado", + "parque", + "párrafo", + "parte", + "pasar", + "paseo", + "pasión", + "paso", + "pasta", + "pata", + "patio", + "patria", + "pausa", + "pauta", + "pavo", + "payaso", + "peatón", + "pecado", + "pecera", + "pecho", + "pedal", + "pedir", + "pegar", + "peine", + "pelar", + "peldaño", + "pelea", + "peligro", + "pellejo", + "pelo", + "peluca", + "pena", + "pensar", + "peñón", + "peón", + "peor", + "pepino", + "pequeño", + "pera", + "percha", + "perder", + "pereza", + "perfil", + "perico", + "perla", + "permiso", + "perro", + "persona", + "pesa", + "pesca", + "pésimo", + "pestaña", + "pétalo", + "petróleo", + "pez", + "pezuña", + "picar", + "pichón", + "pie", + "piedra", + "pierna", + "pieza", + "pijama", + "pilar", + "piloto", + "pimienta", + "pino", + "pintor", + "pinza", + "piña", + "piojo", + "pipa", + "pirata", + "pisar", + "piscina", + "piso", + "pista", + "pitón", + "pizca", + "placa", + "plan", + "plata", + "playa", + "plaza", + "pleito", + "pleno", + "plomo", + "pluma", + "plural", + "pobre", + "poco", + "poder", + "podio", + "poema", + "poesía", + "poeta", + "polen", + "policía", + "pollo", + "polvo", + "pomada", + "pomelo", + "pomo", + "pompa", + "poner", + "porción", + "portal", + "posada", + "poseer", + "posible", + "poste", + "potencia", + "potro", + "pozo", + "prado", + "precoz", + "pregunta", + "premio", + "prensa", + "preso", + "previo", + "primo", + "príncipe", + "prisión", + "privar", + "proa", + "probar", + "proceso", + "producto", + "proeza", + "profesor", + "programa", + "prole", + "promesa", + "pronto", + "propio", + "próximo", + "prueba", + "público", + "puchero", + "pudor", + "pueblo", + "puerta", + "puesto", + "pulga", + "pulir", + "pulmón", + "pulpo", + "pulso", + "puma", + "punto", + "puñal", + "puño", + "pupa", + "pupila", + "puré", + "quedar", + "queja", + "quemar", + "querer", + "queso", + "quieto", + "química", + "quince", + "quitar", + "rábano", + "rabia", + "rabo", + "ración", + "radical", + "raíz", + "rama", + "rampa", + "rancho", + "rango", + "rapaz", + "rápido", + "rapto", + "rasgo", + "raspa", + "rato", + "rayo", + "raza", + "razón", + "reacción", + "realidad", + "rebaño", + "rebote", + "recaer", + "receta", + "rechazo", + "recoger", + "recreo", + "recto", + "recurso", + "red", + "redondo", + "reducir", + "reflejo", + "reforma", + "refrán", + "refugio", + "regalo", + "regir", + "regla", + "regreso", + "rehén", + "reino", + "reír", + "reja", + "relato", + "relevo", + "relieve", + "relleno", + "reloj", + "remar", + "remedio", + "remo", + "rencor", + "rendir", + "renta", + "reparto", + "repetir", + "reposo", + "reptil", + "res", + "rescate", + "resina", + "respeto", + "resto", + "resumen", + "retiro", + "retorno", + "retrato", + "reunir", + "revés", + "revista", + "rey", + "rezar", + "rico", + "riego", + "rienda", + "riesgo", + "rifa", + "rígido", + "rigor", + "rincón", + "riñón", + "río", + "riqueza", + "risa", + "ritmo", + "rito" + }), 4) + { + populate_maps(ALLOW_SHORT_WORDS); + } + }; +} + +#endif diff --git a/src/P2p/NetNode.cpp b/src/P2p/NetNode.cpp index 388a79a..269cd2c 100644 --- a/src/P2p/NetNode.cpp +++ b/src/P2p/NetNode.cpp @@ -218,7 +218,7 @@ namespace CryptoNote s(m_config.m_peer_id, "peer_id"); } -#define INVOKE_HANDLER(CMD, Handler) case CMD::ID: { ret = invokeAdaptor(cmd.buf, out, ctx, boost::bind(Handler, this, _1, _2, _3, _4)); break; } +#define INVOKE_HANDLER(CMD, Handler) case CMD::ID: { ret = invokeAdaptor(cmd.buf, out, ctx, boost::bind(Handler, this, boost::arg<1>(), boost::arg<2>(), boost::arg<3>(), boost::arg<4>())); break; } int NodeServer::handleCommand(const LevinProtocol::Command& cmd, BinaryArray& out, P2pConnectionContext& ctx, bool& handled) { int ret = 0; diff --git a/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp b/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp index f84af42..45230af 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp +++ b/src/PaymentGate/PaymentServiceJsonRpcMessages.cpp @@ -42,6 +42,9 @@ void GetAddresses::Response::serialize(CryptoNote::ISerializer& serializer) { void CreateAddress::Request::serialize(CryptoNote::ISerializer& serializer) { bool hasSecretKey = serializer(spendSecretKey, "spendSecretKey"); bool hasPublicKey = serializer(spendPublicKey, "spendPublicKey"); + + if (!serializer(reset, "reset")) + reset = true; if (hasSecretKey && hasPublicKey) { //TODO: replace it with error codes diff --git a/src/PaymentGate/PaymentServiceJsonRpcMessages.h b/src/PaymentGate/PaymentServiceJsonRpcMessages.h index 70b58f4..d22bfc7 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcMessages.h +++ b/src/PaymentGate/PaymentServiceJsonRpcMessages.h @@ -75,6 +75,9 @@ struct CreateAddress { struct Request { std::string spendSecretKey; std::string spendPublicKey; + + bool reset; + void serialize(CryptoNote::ISerializer& serializer); }; diff --git a/src/PaymentGate/PaymentServiceJsonRpcServer.cpp b/src/PaymentGate/PaymentServiceJsonRpcServer.cpp index 9306159..beb6c51 100644 --- a/src/PaymentGate/PaymentServiceJsonRpcServer.cpp +++ b/src/PaymentGate/PaymentServiceJsonRpcServer.cpp @@ -91,7 +91,7 @@ std::error_code PaymentServiceJsonRpcServer::handleCreateAddress(const CreateAdd if (request.spendSecretKey.empty() && request.spendPublicKey.empty()) { return service.createAddress(response.address); } else if (!request.spendSecretKey.empty()) { - return service.createAddress(request.spendSecretKey, response.address); + return service.createAddress(request.spendSecretKey, request.reset, response.address); } else { return service.createTrackingAddress(request.spendPublicKey, response.address); } diff --git a/src/PaymentGate/WalletService.cpp b/src/PaymentGate/WalletService.cpp index 8388408..3a89389 100644 --- a/src/PaymentGate/WalletService.cpp +++ b/src/PaymentGate/WalletService.cpp @@ -512,7 +512,7 @@ std::error_code WalletService::replaceWithNewWallet(const std::string& viewSecre return std::error_code(); } -std::error_code WalletService::createAddress(const std::string& spendSecretKeyText, std::string& address) { +std::error_code WalletService::createAddress(const std::string& spendSecretKeyText, bool reset, std::string& address) { try { System::EventLock lk(readyEvent); @@ -524,7 +524,7 @@ std::error_code WalletService::createAddress(const std::string& spendSecretKeyTe return make_error_code(CryptoNote::error::WalletServiceErrorCode::WRONG_KEY_FORMAT); } - address = wallet.createAddress(secretKey); + address = wallet.createAddress(secretKey, reset); } catch (std::system_error& x) { logger(Logging::WARNING) << "Error while creating address: " << x.what(); return x.code(); diff --git a/src/PaymentGate/WalletService.h b/src/PaymentGate/WalletService.h index f57ad42..53383f0 100644 --- a/src/PaymentGate/WalletService.h +++ b/src/PaymentGate/WalletService.h @@ -42,7 +42,7 @@ class WalletService { std::error_code resetWallet(); std::error_code replaceWithNewWallet(const std::string& viewSecretKey); - std::error_code createAddress(const std::string& spendSecretKeyText, std::string& address); + std::error_code createAddress(const std::string& spendSecretKeyText, bool reset, std::string& address); std::error_code createAddress(std::string& address); std::error_code createTrackingAddress(const std::string& spendPublicKeyText, std::string& address); std::error_code deleteAddress(const std::string& address); diff --git a/src/Platform/OSX/System/Context.c b/src/Platform/OSX/System/Context.c index 891a4bd..f905d99 100644 --- a/src/Platform/OSX/System/Context.c +++ b/src/Platform/OSX/System/Context.c @@ -4,7 +4,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include -#include "context.h" +#include "Context.h" void makecontext(uctx *ucp, void (*func)(void), intptr_t arg) diff --git a/src/Rpc/CoreRpcServerCommandsDefinitions.h b/src/Rpc/CoreRpcServerCommandsDefinitions.h index df3be15..7392923 100644 --- a/src/Rpc/CoreRpcServerCommandsDefinitions.h +++ b/src/Rpc/CoreRpcServerCommandsDefinitions.h @@ -256,6 +256,7 @@ struct COMMAND_RPC_GET_INFO { struct response { std::string status; + std::string version; uint64_t height; uint64_t difficulty; uint64_t tx_count; @@ -271,6 +272,7 @@ struct COMMAND_RPC_GET_INFO { void serialize(ISerializer &s) { KV_MEMBER(status) + KV_MEMBER(version) KV_MEMBER(height) KV_MEMBER(difficulty) KV_MEMBER(tx_count) @@ -299,7 +301,21 @@ struct COMMAND_RPC_STOP_DAEMON { typedef STATUS_STRUCT response; }; -// +//----------------------------------------------- +struct COMMAND_RPC_GET_PEER_LIST { + typedef EMPTY_STRUCT request; + + struct response { + std::vector peers; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(peers) + KV_MEMBER(status) + } + }; +}; + struct COMMAND_RPC_GETBLOCKCOUNT { typedef std::vector request; @@ -441,6 +457,7 @@ struct f_block_short_response { std::string hash; uint64_t tx_count; uint64_t cumul_size; + difficulty_type difficulty; void serialize(ISerializer &s) { KV_MEMBER(timestamp) @@ -448,6 +465,7 @@ struct f_block_short_response { KV_MEMBER(hash) KV_MEMBER(cumul_size) KV_MEMBER(tx_count) + KV_MEMBER(difficulty) } }; @@ -498,71 +516,6 @@ struct f_block_details_response { KV_MEMBER(totalFeeAmount) } }; -struct currency_base_coin { - std::string name; - std::string git; - - void serialize(ISerializer &s) { - KV_MEMBER(name) - KV_MEMBER(git) - } -}; - -struct currency_core { - std::vector SEED_NODES; - uint64_t EMISSION_SPEED_FACTOR; - uint64_t DIFFICULTY_TARGET; - uint64_t CRYPTONOTE_DISPLAY_DECIMAL_POINT; - std::string MONEY_SUPPLY; -//uint64_t GENESIS_BLOCK_REWARD; - uint64_t DEFAULT_DUST_THRESHOLD; - uint64_t MINIMUM_FEE; - uint64_t CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW; - uint64_t CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE; -// uint64_t CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1; - uint64_t CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX; - uint64_t P2P_DEFAULT_PORT; - uint64_t RPC_DEFAULT_PORT; - uint64_t MAX_BLOCK_SIZE_INITIAL; - uint64_t EXPECTED_NUMBER_OF_BLOCKS_PER_DAY; - uint64_t UPGRADE_HEIGHT; - uint64_t DIFFICULTY_CUT; - uint64_t DIFFICULTY_LAG; - //std::string BYTECOIN_NETWORK; - std::string CRYPTONOTE_NAME; - std::string GENESIS_COINBASE_TX_HEX; - std::vector CHECKPOINTS; - - void serialize(ISerializer &s) { - KV_MEMBER(SEED_NODES) - KV_MEMBER(EMISSION_SPEED_FACTOR) - KV_MEMBER(DIFFICULTY_TARGET) - KV_MEMBER(CRYPTONOTE_DISPLAY_DECIMAL_POINT) - KV_MEMBER(MONEY_SUPPLY) -// KV_MEMBER(GENESIS_BLOCK_REWARD) - KV_MEMBER(DEFAULT_DUST_THRESHOLD) - KV_MEMBER(MINIMUM_FEE) - KV_MEMBER(CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW) - KV_MEMBER(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE) -// KV_MEMBER(CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1) - KV_MEMBER(CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX) - KV_MEMBER(P2P_DEFAULT_PORT) - KV_MEMBER(RPC_DEFAULT_PORT) - KV_MEMBER(MAX_BLOCK_SIZE_INITIAL) - KV_MEMBER(EXPECTED_NUMBER_OF_BLOCKS_PER_DAY) - KV_MEMBER(UPGRADE_HEIGHT) - KV_MEMBER(DIFFICULTY_CUT) - KV_MEMBER(DIFFICULTY_LAG) -// KV_MEMBER(BYTECOIN_NETWORK) - KV_MEMBER(CRYPTONOTE_NAME) - KV_MEMBER(GENESIS_COINBASE_TX_HEX) - KV_MEMBER(CHECKPOINTS) - } -}; - - - - struct COMMAND_RPC_GET_LAST_BLOCK_HEADER { typedef EMPTY_STRUCT request; @@ -658,24 +611,41 @@ struct F_COMMAND_RPC_GET_TRANSACTION_DETAILS { } }; }; -struct F_COMMAND_RPC_GET_BLOCKCHAIN_SETTINGS { - typedef EMPTY_STRUCT request; - struct response { - currency_base_coin base_coin; - currency_core core; - std::vector extensions; - std::string status; - void serialize(ISerializer &s) { - KV_MEMBER(base_coin) - KV_MEMBER(core) - KV_MEMBER(extensions) - KV_MEMBER(status) - } - }; +//----------------------------------------------- +struct K_COMMAND_RPC_GET_TRANSACTIONS_BY_PAYMENT_ID { + struct request { + std::string payment_id; + + void serialize(ISerializer &s) { + KV_MEMBER(payment_id) + } + }; + + struct response { + std::vector transactions; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(transactions) + KV_MEMBER(status) + } + }; }; +struct F_COMMAND_RPC_GET_POOL { + typedef EMPTY_STRUCT request; + struct response { + std::vector transactions; + std::string status; + + void serialize(ISerializer &s) { + KV_MEMBER(transactions) + KV_MEMBER(status) + } + }; +}; struct COMMAND_RPC_QUERY_BLOCKS { struct request { diff --git a/src/Rpc/RpcServer - copy.cpp b/src/Rpc/RpcServer - copy.cpp deleted file mode 100644 index 494c86f..0000000 --- a/src/Rpc/RpcServer - copy.cpp +++ /dev/null @@ -1,651 +0,0 @@ -// Copyright (c) 2011-2016 The Cryptonote developers -// Copyright (c) 2014-2016 SDN developers -// Distributed under the MIT/X11 software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "RpcServer.h" - -#include -#include - -// CryptoNote -#include "Common/StringTools.h" -#include "CryptoNoteCore/CryptoNoteTools.h" -#include "CryptoNoteCore/Core.h" -#include "CryptoNoteCore/IBlock.h" -#include "CryptoNoteCore/Miner.h" -#include "CryptoNoteCore/TransactionExtra.h" - -#include "CryptoNoteProtocol/ICryptoNoteProtocolQuery.h" - -#include "P2p/NetNode.h" - -#include "CoreRpcServerErrorCodes.h" -#include "JsonRpc.h" - -#undef ERROR - -using namespace Logging; -using namespace Crypto; -using namespace Common; - -namespace CryptoNote { - -namespace { - -template -RpcServer::HandlerFunction binMethod(bool (RpcServer::*handler)(typename Command::request const&, typename Command::response&)) { - return [handler](RpcServer* obj, const HttpRequest& request, HttpResponse& response) { - - boost::value_initialized req; - boost::value_initialized res; - - if (!loadFromBinaryKeyValue(static_cast(req), request.getBody())) { - return false; - } - - bool result = (obj->*handler)(req, res); - response.setBody(storeToBinaryKeyValue(res.data())); - return result; - }; -} - -template -RpcServer::HandlerFunction jsonMethod(bool (RpcServer::*handler)(typename Command::request const&, typename Command::response&)) { - return [handler](RpcServer* obj, const HttpRequest& request, HttpResponse& response) { - - boost::value_initialized req; - boost::value_initialized res; - - if (!loadFromJson(static_cast(req), request.getBody())) { - return false; - } - - bool result = (obj->*handler)(req, res); - response.setBody(storeToJson(res.data())); - return result; - }; -} - -} - -std::unordered_map> RpcServer::s_handlers = { - - // binary handlers - { "/getblocks.bin", { binMethod(&RpcServer::on_get_blocks), false } }, - { "/queryblocks.bin", { binMethod(&RpcServer::on_query_blocks), false } }, - { "/queryblockslite.bin", { binMethod(&RpcServer::on_query_blocks_lite), false } }, - { "/get_o_indexes.bin", { binMethod(&RpcServer::on_get_indexes), false } }, - { "/getrandom_outs.bin", { binMethod(&RpcServer::on_get_random_outs), false } }, - { "/get_pool_changes.bin", { binMethod(&RpcServer::onGetPoolChanges), false } }, - { "/get_pool_changes_lite.bin", { binMethod(&RpcServer::onGetPoolChangesLite), false } }, - - // json handlers - { "/getinfo", { jsonMethod(&RpcServer::on_get_info), true } }, - { "/getheight", { jsonMethod(&RpcServer::on_get_height), true } }, - { "/gettransactions", { jsonMethod(&RpcServer::on_get_transactions), false } }, - { "/sendrawtransaction", { jsonMethod(&RpcServer::on_send_raw_tx), false } }, - { "/start_mining", { jsonMethod(&RpcServer::on_start_mining), false } }, - { "/stop_mining", { jsonMethod(&RpcServer::on_stop_mining), false } }, - { "/stop_daemon", { jsonMethod(&RpcServer::on_stop_daemon), true } }, - - // json rpc - { "/json_rpc", { std::bind(&RpcServer::processJsonRpcRequest, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), true } } -}; - -RpcServer::RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery) : - HttpServer(dispatcher, log), logger(log, "RpcServer"), m_core(c), m_p2p(p2p), m_protocolQuery(protocolQuery) { -} - -void RpcServer::processRequest(const HttpRequest& request, HttpResponse& response) { - auto url = request.getUrl(); - - auto it = s_handlers.find(url); - if (it == s_handlers.end()) { - response.setStatus(HttpResponse::STATUS_404); - return; - } - - if (!it->second.allowBusyCore && !isCoreReady()) { - response.setStatus(HttpResponse::STATUS_500); - response.setBody("Core is busy"); - return; - } - - it->second.handler(this, request, response); -} - -bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& response) { - - using namespace JsonRpc; - - response.addHeader("Content-Type", "application/json"); - - JsonRpcRequest jsonRequest; - JsonRpcResponse jsonResponse; - - try { - logger(TRACE) << "JSON-RPC request: " << request.getBody(); - jsonRequest.parseRequest(request.getBody()); - jsonResponse.setId(jsonRequest.getId()); // copy id - - static std::unordered_map> jsonRpcHandlers = { - { "getblockcount", { makeMemberMethod(&RpcServer::on_getblockcount), true } }, - { "on_getblockhash", { makeMemberMethod(&RpcServer::on_getblockhash), false } }, - { "getblocktemplate", { makeMemberMethod(&RpcServer::on_getblocktemplate), false } }, - { "getcurrencyid", { makeMemberMethod(&RpcServer::on_get_currency_id), true } }, - { "submitblock", { makeMemberMethod(&RpcServer::on_submitblock), false } }, - { "getlastblockheader", { makeMemberMethod(&RpcServer::on_get_last_block_header), false } }, - { "getblockheaderbyhash", { makeMemberMethod(&RpcServer::on_get_block_header_by_hash), false } }, - { "getblockheaderbyheight", { makeMemberMethod(&RpcServer::on_get_block_header_by_height), false } } - }; - - auto it = jsonRpcHandlers.find(jsonRequest.getMethod()); - if (it == jsonRpcHandlers.end()) { - throw JsonRpcError(JsonRpc::errMethodNotFound); - } - - if (!it->second.allowBusyCore && !isCoreReady()) { - throw JsonRpcError(CORE_RPC_ERROR_CODE_CORE_BUSY, "Core is busy"); - } - - it->second.handler(this, jsonRequest, jsonResponse); - - } catch (const JsonRpcError& err) { - jsonResponse.setError(err); - } catch (const std::exception& e) { - jsonResponse.setError(JsonRpcError(JsonRpc::errInternalError, e.what())); - } - - response.setBody(jsonResponse.getBody()); - logger(TRACE) << "JSON-RPC response: " << jsonResponse.getBody(); - return true; -} - -bool RpcServer::isCoreReady() { - return m_core.currency().isTestnet() || m_p2p.get_payload_object().isSynchronized(); -} - -// -// Binary handlers -// - -bool RpcServer::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res) { - // TODO code duplication see InProcessNode::doGetNewBlocks() - if (req.block_ids.empty()) { - res.status = "Failed"; - return false; - } - - if (req.block_ids.back() != m_core.getBlockIdByHeight(0)) { - res.status = "Failed"; - return false; - } - - uint32_t totalBlockCount; - uint32_t startBlockIndex; - std::vector supplement = m_core.findBlockchainSupplement(req.block_ids, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT, totalBlockCount, startBlockIndex); - - res.current_height = totalBlockCount; - res.start_height = startBlockIndex; - - for (const auto& blockId : supplement) { - assert(m_core.have_block(blockId)); - auto completeBlock = m_core.getBlock(blockId); - assert(completeBlock != nullptr); - - res.blocks.resize(res.blocks.size() + 1); - res.blocks.back().block = asString(toBinaryArray(completeBlock->getBlock())); - - res.blocks.back().txs.reserve(completeBlock->getTransactionCount()); - for (size_t i = 0; i < completeBlock->getTransactionCount(); ++i) { - res.blocks.back().txs.push_back(asString(toBinaryArray(completeBlock->getTransaction(i)))); - } - } - - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_query_blocks(const COMMAND_RPC_QUERY_BLOCKS::request& req, COMMAND_RPC_QUERY_BLOCKS::response& res) { - uint32_t startHeight; - uint32_t currentHeight; - uint32_t fullOffset; - - if (!m_core.queryBlocks(req.block_ids, req.timestamp, startHeight, currentHeight, fullOffset, res.items)) { - res.status = "Failed to perform query"; - return false; - } - - res.start_height = startHeight; - res.current_height = currentHeight; - res.full_offset = fullOffset; - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_query_blocks_lite(const COMMAND_RPC_QUERY_BLOCKS_LITE::request& req, COMMAND_RPC_QUERY_BLOCKS_LITE::response& res) { - uint32_t startHeight; - uint32_t currentHeight; - uint32_t fullOffset; - if (!m_core.queryBlocksLite(req.blockIds, req.timestamp, startHeight, currentHeight, fullOffset, res.items)) { - res.status = "Failed to perform query"; - return false; - } - - res.startHeight = startHeight; - res.currentHeight = currentHeight; - res.fullOffset = fullOffset; - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res) { - std::vector outputIndexes; - if (!m_core.get_tx_outputs_gindexs(req.txid, outputIndexes)) { - res.status = "Failed"; - return true; - } - - res.o_indexes.assign(outputIndexes.begin(), outputIndexes.end()); - res.status = CORE_RPC_STATUS_OK; - logger(TRACE) << "COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES: [" << res.o_indexes.size() << "]"; - return true; -} - -bool RpcServer::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) { - res.status = "Failed"; - if (!m_core.get_random_outs_for_amounts(req, res)) { - return true; - } - - res.status = CORE_RPC_STATUS_OK; - - std::stringstream ss; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount outs_for_amount; - typedef COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry out_entry; - - std::for_each(res.outs.begin(), res.outs.end(), [&](outs_for_amount& ofa) { - ss << "[" << ofa.amount << "]:"; - - assert(ofa.outs.size() && "internal error: ofa.outs.size() is empty"); - - std::for_each(ofa.outs.begin(), ofa.outs.end(), [&](out_entry& oe) - { - ss << oe.global_amount_index << " "; - }); - ss << ENDL; - }); - std::string s = ss.str(); - logger(TRACE) << "COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS: " << ENDL << s; - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::onGetPoolChanges(const COMMAND_RPC_GET_POOL_CHANGES::request& req, COMMAND_RPC_GET_POOL_CHANGES::response& rsp) { - rsp.status = CORE_RPC_STATUS_OK; - std::vector addedTransactions; - rsp.isTailBlockActual = m_core.getPoolChanges(req.tailBlockId, req.knownTxsIds, addedTransactions, rsp.deletedTxsIds); - for (auto& tx : addedTransactions) { - BinaryArray txBlob; - if (!toBinaryArray(tx, txBlob)) { - rsp.status = "Internal error"; - break;; - } - - rsp.addedTxs.emplace_back(std::move(txBlob)); - } - return true; -} - - -bool RpcServer::onGetPoolChangesLite(const COMMAND_RPC_GET_POOL_CHANGES_LITE::request& req, COMMAND_RPC_GET_POOL_CHANGES_LITE::response& rsp) { - rsp.status = CORE_RPC_STATUS_OK; - rsp.isTailBlockActual = m_core.getPoolChangesLite(req.tailBlockId, req.knownTxsIds, rsp.addedTxs, rsp.deletedTxsIds); - - return true; -} - -// -// JSON handlers -// - -bool RpcServer::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res) { - res.height = m_core.get_current_blockchain_height(); - res.difficulty = m_core.getNextBlockDifficulty(); - res.tx_count = m_core.get_blockchain_total_transactions() - res.height; //without coinbase - res.tx_pool_size = m_core.get_pool_transactions_count(); - res.alt_blocks_count = m_core.get_alternative_blocks_count(); - uint64_t total_conn = m_p2p.get_connections_count(); - res.outgoing_connections_count = m_p2p.get_outgoing_connections_count(); - res.incoming_connections_count = total_conn - res.outgoing_connections_count; - res.white_peerlist_size = m_p2p.getPeerlistManager().get_white_peers_count(); - res.grey_peerlist_size = m_p2p.getPeerlistManager().get_gray_peers_count(); - res.last_known_block_index = std::max(static_cast(1), m_protocolQuery.getObservedHeight()) - 1; - res.full_deposit_amount = m_core.fullDepositAmount(); - res.full_deposit_interest = m_core.fullDepositInterest(); - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res) { - res.height = m_core.get_current_blockchain_height(); - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res) { - std::vector vh; - for (const auto& tx_hex_str : req.txs_hashes) { - BinaryArray b; - if (!fromHex(tx_hex_str, b)) - { - res.status = "Failed to parse hex representation of transaction hash"; - return true; - } - if (b.size() != sizeof(Hash)) - { - res.status = "Failed, size of data mismatch"; - } - vh.push_back(*reinterpret_cast(b.data())); - } - std::list missed_txs; - std::list txs; - m_core.getTransactions(vh, txs, missed_txs); - - for (auto& tx : txs) { - res.txs_as_hex.push_back(toHex(toBinaryArray(tx))); - } - - for (const auto& miss_tx : missed_txs) { - res.missed_tx.push_back(Common::podToHex(miss_tx)); - } - - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res) { - BinaryArray tx_blob; - if (!fromHex(req.tx_as_hex, tx_blob)) - { - logger(INFO) << "[on_send_raw_tx]: Failed to parse tx from hexbuff: " << req.tx_as_hex; - res.status = "Failed"; - return true; - } - - tx_verification_context tvc = boost::value_initialized(); - if (!m_core.handle_incoming_tx(tx_blob, tvc, false)) - { - logger(INFO) << "[on_send_raw_tx]: Failed to process tx"; - res.status = "Failed"; - return true; - } - - if (tvc.m_verifivation_failed) - { - logger(INFO) << "[on_send_raw_tx]: tx verification failed"; - res.status = "Failed"; - return true; - } - - if (!tvc.m_should_be_relayed) - { - logger(INFO) << "[on_send_raw_tx]: tx accepted, but not relayed"; - res.status = "Not relayed"; - return true; - } - - - NOTIFY_NEW_TRANSACTIONS::request r; - r.txs.push_back(asString(tx_blob)); - m_core.get_protocol()->relay_transactions(r); - //TODO: make sure that tx has reached other nodes here, probably wait to receive reflections from other nodes - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res) { - AccountPublicAddress adr; - if (!m_core.currency().parseAccountAddressString(req.miner_address, adr)) { - res.status = "Failed, wrong address"; - return true; - } - - if (!m_core.get_miner().start(adr, static_cast(req.threads_count))) { - res.status = "Failed, mining not started"; - return true; - } - - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res) { - if (!m_core.get_miner().stop()) { - res.status = "Failed, mining not stopped"; - return true; - } - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res) { - if (m_core.currency().isTestnet()) { - m_p2p.sendStopSignal(); - res.status = CORE_RPC_STATUS_OK; - } else { - res.status = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; - return false; - } - return true; -} - -//------------------------------------------------------------------------------------------------------------------------------ -// JSON RPC methods -//------------------------------------------------------------------------------------------------------------------------------ -bool RpcServer::on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res) { - res.count = m_core.get_current_blockchain_height(); - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res) { - if (req.size() != 1) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_PARAM, "Wrong parameters, expected height" }; - } - - uint32_t h = static_cast(req[0]); - Crypto::Hash blockId = m_core.getBlockIdByHeight(h); - if (blockId == NULL_HASH) { - throw JsonRpc::JsonRpcError{ - CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT, - std::string("To big height: ") + std::to_string(h) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height()) - }; - } - - res = Common::podToHex(blockId); - return true; -} - -namespace { - uint64_t slow_memmem(void* start_buff, size_t buflen, void* pat, size_t patlen) - { - void* buf = start_buff; - void* end = (char*)buf + buflen - patlen; - while ((buf = memchr(buf, ((char*)pat)[0], buflen))) - { - if (buf>end) - return 0; - if (memcmp(buf, pat, patlen) == 0) - return (char*)buf - (char*)start_buff; - buf = (char*)buf + 1; - } - return 0; - } -} - -bool RpcServer::on_getblocktemplate(const COMMAND_RPC_GETBLOCKTEMPLATE::request& req, COMMAND_RPC_GETBLOCKTEMPLATE::response& res) { - if (req.reserve_size > TX_EXTRA_NONCE_MAX_COUNT) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_TOO_BIG_RESERVE_SIZE, "To big reserved size, maximum 255" }; - } - - AccountPublicAddress acc = boost::value_initialized(); - - if (!req.wallet_address.size() || !m_core.currency().parseAccountAddressString(req.wallet_address, acc)) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_WALLET_ADDRESS, "Failed to parse wallet address" }; - } - - Block b = boost::value_initialized(); - CryptoNote::BinaryArray blob_reserve; - blob_reserve.resize(req.reserve_size, 0); - if (!m_core.get_block_template(b, acc, res.difficulty, res.height, blob_reserve)) { - logger(ERROR) << "Failed to create block template"; - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: failed to create block template" }; - } - - BinaryArray block_blob = toBinaryArray(b); - PublicKey tx_pub_key = CryptoNote::getTransactionPublicKeyFromExtra(b.baseTransaction.extra); - if (tx_pub_key == NULL_PUBLIC_KEY) { - logger(ERROR) << "Failed to find tx pub key in coinbase extra"; - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: failed to find tx pub key in coinbase extra" }; - } - - if (0 < req.reserve_size) { - res.reserved_offset = slow_memmem((void*)block_blob.data(), block_blob.size(), &tx_pub_key, sizeof(tx_pub_key)); - if (!res.reserved_offset) { - logger(ERROR) << "Failed to find tx pub key in blockblob"; - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: failed to create block template" }; - } - res.reserved_offset += sizeof(tx_pub_key) + 3; //3 bytes: tag for TX_EXTRA_TAG_PUBKEY(1 byte), tag for TX_EXTRA_NONCE(1 byte), counter in TX_EXTRA_NONCE(1 byte) - if (res.reserved_offset + req.reserve_size > block_blob.size()) { - logger(ERROR) << "Failed to calculate offset for reserved bytes"; - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: failed to create block template" }; - } - } else { - res.reserved_offset = 0; - } - - res.blocktemplate_blob = toHex(block_blob); - res.status = CORE_RPC_STATUS_OK; - - return true; -} - -bool RpcServer::on_get_currency_id(const COMMAND_RPC_GET_CURRENCY_ID::request& /*req*/, COMMAND_RPC_GET_CURRENCY_ID::response& res) { - Hash currencyId = m_core.currency().genesisBlockHash(); - res.currency_id_blob = Common::podToHex(currencyId); - return true; -} - -bool RpcServer::on_submitblock(const COMMAND_RPC_SUBMITBLOCK::request& req, COMMAND_RPC_SUBMITBLOCK::response& res) { - if (req.size() != 1) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_PARAM, "Wrong param" }; - } - - BinaryArray blockblob; - if (!fromHex(req[0], blockblob)) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB, "Wrong block blob" }; - } - - block_verification_context bvc = boost::value_initialized(); - - m_core.handle_incoming_block_blob(blockblob, bvc, true, true); - - if (!bvc.m_added_to_main_chain) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED, "Block not accepted" }; - } - - res.status = CORE_RPC_STATUS_OK; - return true; -} - - -namespace { - uint64_t get_block_reward(const Block& blk) { - uint64_t reward = 0; - for (const TransactionOutput& out : blk.baseTransaction.outputs) { - reward += out.amount; - } - return reward; - } -} - -void RpcServer::fill_block_header_response(const Block& blk, bool orphan_status, uint64_t height, const Hash& hash, block_header_response& responce) { - responce.major_version = blk.majorVersion; - responce.minor_version = blk.minorVersion; - responce.timestamp = blk.timestamp; - responce.prev_hash = Common::podToHex(blk.previousBlockHash); - responce.nonce = blk.nonce; - responce.orphan_status = orphan_status; - responce.height = height; - responce.depth = m_core.get_current_blockchain_height() - height - 1; - responce.hash = Common::podToHex(hash); - m_core.getBlockDifficulty(static_cast(height), responce.difficulty); - responce.reward = get_block_reward(blk); -} - -bool RpcServer::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res) { - uint32_t last_block_height; - Hash last_block_hash; - - m_core.get_blockchain_top(last_block_height, last_block_hash); - - Block last_block; - if (!m_core.getBlockByHash(last_block_hash, last_block)) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, "Internal error: can't get last block hash." }; - } - - fill_block_header_response(last_block, false, last_block_height, last_block_hash, res.block_header); - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res) { - Hash block_hash; - - if (!parse_hash256(req.hash, block_hash)) { - throw JsonRpc::JsonRpcError{ - CORE_RPC_ERROR_CODE_WRONG_PARAM, - "Failed to parse hex representation of block hash. Hex = " + req.hash + '.' }; - } - - Block blk; - if (!m_core.getBlockByHash(block_hash, blk)) { - throw JsonRpc::JsonRpcError{ - CORE_RPC_ERROR_CODE_INTERNAL_ERROR, - "Internal error: can't get block by hash. Hash = " + req.hash + '.' }; - } - - if (blk.baseTransaction.inputs.front().type() != typeid(BaseInput)) { - throw JsonRpc::JsonRpcError{ - CORE_RPC_ERROR_CODE_INTERNAL_ERROR, - "Internal error: coinbase transaction in the block has the wrong type" }; - } - - uint64_t block_height = boost::get(blk.baseTransaction.inputs.front()).blockIndex; - fill_block_header_response(blk, false, block_height, block_hash, res.block_header); - res.status = CORE_RPC_STATUS_OK; - return true; -} - -bool RpcServer::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res) { - if (m_core.get_current_blockchain_height() <= req.height) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_TOO_BIG_HEIGHT, - std::string("To big height: ") + std::to_string(req.height) + ", current blockchain height = " + std::to_string(m_core.get_current_blockchain_height()) }; - } - - Hash block_hash = m_core.getBlockIdByHeight(static_cast(req.height)); - Block blk; - if (!m_core.getBlockByHash(block_hash, blk)) { - throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_INTERNAL_ERROR, - "Internal error: can't get block by height. Height = " + std::to_string(req.height) + '.' }; - } - - fill_block_header_response(blk, false, req.height, block_hash, res.block_header); - res.status = CORE_RPC_STATUS_OK; - return true; -} - - -} diff --git a/src/Rpc/RpcServer.cpp b/src/Rpc/RpcServer.cpp index 9e8f56a..2c9b012 100644 --- a/src/Rpc/RpcServer.cpp +++ b/src/Rpc/RpcServer.cpp @@ -1,9 +1,11 @@ // Copyright (c) 2011-2016 The Cryptonote developers // Copyright (c) 2014-2016 SDN developers +// Copyright (c) 2016 - 2018, The Karbo developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "RpcServer.h" +#include "version.h" #include #include @@ -11,6 +13,7 @@ // CryptoNote #include "Common/StringTools.h" #include "CryptoNoteCore/CryptoNoteTools.h" +#include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/Core.h" #include "CryptoNoteCore/IBlock.h" #include "CryptoNoteCore/Miner.h" @@ -88,6 +91,7 @@ std::unordered_map(&RpcServer::on_start_mining), false } }, { "/stop_mining", { jsonMethod(&RpcServer::on_stop_mining), false } }, { "/stop_daemon", { jsonMethod(&RpcServer::on_stop_daemon), true } }, + { "/peers", { jsonMethod(&RpcServer::on_get_peer_list), true } }, // json rpc { "/json_rpc", { std::bind(&RpcServer::processJsonRpcRequest, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), true } } @@ -120,6 +124,9 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& using namespace JsonRpc; response.addHeader("Content-Type", "application/json"); + if (!m_cors_domain.empty()) { + response.addHeader("Access-Control-Allow-Origin", m_cors_domain); + } JsonRpcRequest jsonRequest; JsonRpcResponse jsonResponse; @@ -133,7 +140,6 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& { "f_blocks_list_json", { makeMemberMethod(&RpcServer::f_on_blocks_list_json), false } }, { "f_block_json", { makeMemberMethod(&RpcServer::f_on_block_json), false } }, { "f_transaction_json", { makeMemberMethod(&RpcServer::f_on_transaction_json), false } }, - // { "f_get_blockchain_settings", { makeMemberMethod(&RpcServer::f_on_get_blockchain_settings), true } }, { "getblockcount", { makeMemberMethod(&RpcServer::on_getblockcount), true } }, { "on_getblockhash", { makeMemberMethod(&RpcServer::on_getblockhash), false } }, { "getblocktemplate", { makeMemberMethod(&RpcServer::on_getblocktemplate), false } }, @@ -141,7 +147,9 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& { "submitblock", { makeMemberMethod(&RpcServer::on_submitblock), false } }, { "getlastblockheader", { makeMemberMethod(&RpcServer::on_get_last_block_header), false } }, { "getblockheaderbyhash", { makeMemberMethod(&RpcServer::on_get_block_header_by_hash), false } }, - { "getblockheaderbyheight", { makeMemberMethod(&RpcServer::on_get_block_header_by_height), false } } + { "getblockheaderbyheight", { makeMemberMethod(&RpcServer::on_get_block_header_by_height), false } }, + { "f_pool_json", { makeMemberMethod(&RpcServer::f_on_pool_json), false } }, + { "k_transactions_by_payment_id", { makeMemberMethod(&RpcServer::k_on_transactions_by_payment_id), false } } }; auto it = jsonRpcHandlers.find(jsonRequest.getMethod()); @@ -166,6 +174,16 @@ bool RpcServer::processJsonRpcRequest(const HttpRequest& request, HttpResponse& return true; } +bool RpcServer::restrictRPC(const bool is_restricted) { + m_restricted_rpc = is_restricted; + return true; +} + +bool RpcServer::enableCors(const std::string domain) { + m_cors_domain = domain; + return true; +} + bool RpcServer::isCoreReady() { return m_core.currency().isTestnet() || m_p2p.get_payload_object().isSynchronized(); } @@ -328,6 +346,7 @@ bool RpcServer::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RP res.last_known_block_index = std::max(static_cast(1), m_protocolQuery.getObservedHeight()) - 1; res.full_deposit_amount = m_core.fullDepositAmount(); res.full_deposit_interest = m_core.fullDepositInterest(); + res.version = PROJECT_VERSION_LONG; res.status = CORE_RPC_STATUS_OK; return true; } @@ -410,6 +429,10 @@ bool RpcServer::on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMM } bool RpcServer::on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res) { + if (m_restricted_rpc) { + res.status = "Failed, restricted handle"; + return false; + } AccountPublicAddress adr; if (!m_core.currency().parseAccountAddressString(req.miner_address, adr)) { res.status = "Failed, wrong address"; @@ -426,6 +449,10 @@ bool RpcServer::on_start_mining(const COMMAND_RPC_START_MINING::request& req, CO } bool RpcServer::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res) { + if (m_restricted_rpc) { + res.status = "Failed, restricted handle"; + return false; + } if (!m_core.get_miner().stop()) { res.status = "Failed, mining not stopped"; return true; @@ -435,6 +462,10 @@ bool RpcServer::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMM } bool RpcServer::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res) { + if (m_restricted_rpc) { + res.status = "Failed, restricted handle"; + return false; + } if (m_core.currency().isTestnet()) { m_p2p.sendStopSignal(); res.status = CORE_RPC_STATUS_OK; @@ -445,6 +476,19 @@ bool RpcServer::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMM return true; } +bool RpcServer::on_get_peer_list(const COMMAND_RPC_GET_PEER_LIST::request& req, COMMAND_RPC_GET_PEER_LIST::response& res) { + std::list pl_wite; + std::list pl_gray; + m_p2p.getPeerlistManager().get_peerlist_full(pl_gray, pl_wite); + for (const auto& pe : pl_wite) { + std::stringstream ss; + ss << pe.adr; + res.peers.push_back(ss.str()); + } + res.status = CORE_RPC_STATUS_OK; + return true; +} + //------------------------------------------------------------------------------------------------------------------------------ // JSON RPC methods //------------------------------------------------------------------------------------------------------------------------------ @@ -472,6 +516,8 @@ bool RpcServer::f_on_blocks_list_json(const F_COMMAND_RPC_GET_BLOCKS_LIST::reque m_core.getBlockSize(block_hash, tx_cumulative_block_size); size_t blokBlobSize = getObjectBinarySize(blk); size_t minerTxBlobSize = getObjectBinarySize(blk.baseTransaction); + difficulty_type blockDiff; + m_core.getBlockDifficulty(static_cast(i), blockDiff); f_block_short_response block_short; block_short.cumul_size = blokBlobSize + tx_cumulative_block_size - minerTxBlobSize; @@ -480,6 +526,7 @@ bool RpcServer::f_on_blocks_list_json(const F_COMMAND_RPC_GET_BLOCKS_LIST::reque block_short.hash = Common::podToHex(block_hash); block_short.cumul_size = blokBlobSize + tx_cumulative_block_size - minerTxBlobSize; block_short.tx_count = blk.transactionHashes.size() + 1; + block_short.difficulty = blockDiff; res.blocks.push_back(block_short); @@ -494,10 +541,15 @@ bool RpcServer::f_on_blocks_list_json(const F_COMMAND_RPC_GET_BLOCKS_LIST::reque bool RpcServer::f_on_block_json(const F_COMMAND_RPC_GET_BLOCK_DETAILS::request& req, F_COMMAND_RPC_GET_BLOCK_DETAILS::response& res) { Hash hash; - if (!parse_hash256(req.hash, hash)) { - throw JsonRpc::JsonRpcError{ - CORE_RPC_ERROR_CODE_WRONG_PARAM, - "Failed to parse hex representation of block hash. Hex = " + req.hash + '.' }; + try { + uint32_t height = boost::lexical_cast(req.hash); + hash = m_core.getBlockIdByHeight(height); + } catch (boost::bad_lexical_cast &) { + if (!parse_hash256(req.hash, hash)) { + throw JsonRpc::JsonRpcError{ + CORE_RPC_ERROR_CODE_WRONG_PARAM, + "Failed to parse hex representation of block hash. Hex = " + req.hash + '.' }; + } } Block blk; @@ -703,6 +755,24 @@ bool RpcServer::f_on_transaction_json(const F_COMMAND_RPC_GET_TRANSACTION_DETAIL return true; } +bool RpcServer::f_on_pool_json(const F_COMMAND_RPC_GET_POOL::request& req, F_COMMAND_RPC_GET_POOL::response& res) { + auto pool = m_core.getPoolTransactions(); + for (const Transaction tx : pool) { + f_transaction_short_response transaction_short; + + uint64_t amount_in = getInputAmount(tx); + uint64_t amount_out = getOutputAmount(tx); + + transaction_short.hash = Common::podToHex(getObjectHash(tx)); + transaction_short.fee = amount_in < amount_out + parameters::MINIMUM_FEE ? parameters::MINIMUM_FEE : amount_in - amount_out; + transaction_short.amount_out = amount_out; + transaction_short.size = getObjectBinarySize(tx); + res.transactions.push_back(transaction_short); + } + res.status = CORE_RPC_STATUS_OK; + return true; +} + bool RpcServer::f_getMixin(const Transaction& transaction, uint64_t& mixin) { mixin = 0; for (const TransactionInput& txin : transaction.inputs) { @@ -717,6 +787,43 @@ bool RpcServer::f_getMixin(const Transaction& transaction, uint64_t& mixin) { return true; } +bool RpcServer::k_on_transactions_by_payment_id(const K_COMMAND_RPC_GET_TRANSACTIONS_BY_PAYMENT_ID::request& req, K_COMMAND_RPC_GET_TRANSACTIONS_BY_PAYMENT_ID::response& res) { + if (!req.payment_id.size()) { + throw JsonRpc::JsonRpcError{ CORE_RPC_ERROR_CODE_WRONG_PARAM, "Wrong parameters, expected payment_id" }; + } + logger(Logging::INFO, Logging::WHITE) << "RPC request came: Search by Payment ID: " << req.payment_id; + + Crypto::Hash paymentId; + std::vector transactions; + + if (!parse_hash256(req.payment_id, paymentId)) { + throw JsonRpc::JsonRpcError{ + CORE_RPC_ERROR_CODE_WRONG_PARAM, + "Failed to parse Payment ID: " + req.payment_id + '.' }; + } + + if (!m_core.getTransactionsByPaymentId(paymentId, transactions)) { + throw JsonRpc::JsonRpcError{ + CORE_RPC_ERROR_CODE_INTERNAL_ERROR, + "Internal error: can't get transactions by Payment ID: " + req.payment_id + '.' }; + } + + for (const Transaction& tx : transactions) { + f_transaction_short_response transaction_short; + uint64_t amount_in = 0; + get_inputs_money_amount(tx, amount_in); + uint64_t amount_out = get_outs_money_amount(tx); + + transaction_short.hash = Common::podToHex(getObjectHash(tx)); + transaction_short.fee = amount_in - amount_out; + transaction_short.amount_out = amount_out; + transaction_short.size = getObjectBinarySize(tx); + res.transactions.push_back(transaction_short); + } + + res.status = CORE_RPC_STATUS_OK; + return true; +} bool RpcServer::on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res) { res.count = m_core.get_current_blockchain_height(); diff --git a/src/Rpc/RpcServer.h b/src/Rpc/RpcServer.h index 90d9bef..1b2a3e4 100644 --- a/src/Rpc/RpcServer.h +++ b/src/Rpc/RpcServer.h @@ -1,5 +1,6 @@ // Copyright (c) 2011-2016 The Cryptonote developers // Copyright (c) 2014-2016 SDN developers +// Copyright (c) 2016 - 2018, The Karbo developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -23,6 +24,8 @@ class RpcServer : public HttpServer { RpcServer(System::Dispatcher& dispatcher, Logging::ILogger& log, core& c, NodeServer& p2p, const ICryptoNoteProtocolQuery& protocolQuery); typedef std::function HandlerFunction; + bool enableCors(const std::string domain); + bool restrictRPC(const bool is_resctricted); private: @@ -56,6 +59,9 @@ class RpcServer : public HttpServer { bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res); bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res); bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res); + bool on_get_peer_list(const COMMAND_RPC_GET_PEER_LIST::request& req, COMMAND_RPC_GET_PEER_LIST::response& res); + bool f_on_pool_json(const F_COMMAND_RPC_GET_POOL::request& req, F_COMMAND_RPC_GET_POOL::response& res); + bool k_on_transactions_by_payment_id(const K_COMMAND_RPC_GET_TRANSACTIONS_BY_PAYMENT_ID::request& req, K_COMMAND_RPC_GET_TRANSACTIONS_BY_PAYMENT_ID::response& res); // json rpc bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res); @@ -79,6 +85,8 @@ class RpcServer : public HttpServer { core& m_core; NodeServer& m_p2p; const ICryptoNoteProtocolQuery& m_protocolQuery; + bool m_restricted_rpc; + std::string m_cors_domain; }; } diff --git a/src/SimpleWallet/SimpleWallet.cpp b/src/SimpleWallet/SimpleWallet.cpp index 7211adf..ea3528d 100644 --- a/src/SimpleWallet/SimpleWallet.cpp +++ b/src/SimpleWallet/SimpleWallet.cpp @@ -22,6 +22,7 @@ #include "Common/CommandLine.h" #include "Common/SignalHandler.h" #include "Common/StringTools.h" +#include #include "Common/PathTools.h" #include "Common/Util.h" #include "CryptoNoteCore/CryptoNoteFormatUtils.h" @@ -37,6 +38,8 @@ #include "version.h" +#include "Mnemonics/electrum-words.h" + #include #if defined(WIN32) @@ -58,6 +61,9 @@ const command_line::arg_descriptor arg_wallet_file = { "wallet-file const command_line::arg_descriptor arg_generate_new_wallet = { "generate-new-wallet", "Generate new wallet and save it to ", "" }; const command_line::arg_descriptor arg_daemon_address = { "daemon-address", "Use daemon instance at :", "" }; const command_line::arg_descriptor arg_daemon_host = { "daemon-host", "Use daemon instance at host instead of localhost", "" }; +const command_line::arg_descriptor arg_mnemonic_seed = { "mnemonic-seed", "Specify mnemonic seed for wallet recovery/creation", "" }; +const command_line::arg_descriptor arg_restore_deterministic_wallet = { "restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false }; +const command_line::arg_descriptor arg_non_deterministic = { "non-deterministic", "Creates non-deterministic (classic) view and spend keys", false }; const command_line::arg_descriptor arg_password = { "password", "Wallet password", "", true }; const command_line::arg_descriptor arg_daemon_port = { "daemon-port", "Use daemon instance at port instead of 8081", 0 }; const command_line::arg_descriptor arg_log_level = { "set_log", "", INFO, true }; @@ -137,9 +143,11 @@ struct TransferCommand { std::vector extra; uint64_t fee; std::map> aliases; + std::vector messages; + uint64_t ttl; TransferCommand(const CryptoNote::Currency& currency) : - m_currency(currency), fake_outs_count(0), fee(currency.minimumFee()) { + m_currency(currency), fake_outs_count(0), fee(currency.minimumFee()), ttl(0) { } bool parseArguments(LoggerRef& logger, const std::vector &args) { @@ -155,6 +163,8 @@ struct TransferCommand { return false; } + bool feeFound = false; + bool ttlFound = false; while (!ar.eof()) { auto arg = ar.next(); @@ -169,6 +179,13 @@ struct TransferCommand { return false; } } else if (arg == "-f") { + feeFound = true; + + if (ttlFound) { + logger(ERROR, BRIGHT_RED) << "Transaction with TTL can not have fee"; + return false; + } + bool ok = m_currency.parseAmount(value, fee); if (!ok) { logger(ERROR, BRIGHT_RED) << "Fee value is invalid: " << value; @@ -179,6 +196,23 @@ struct TransferCommand { logger(ERROR, BRIGHT_RED) << "Fee value is less than minimum: " << m_currency.minimumFee(); return false; } + } else if (arg == "-m") { + messages.emplace_back(value); + } else if (arg == "-ttl") { + ttlFound = true; + + if (feeFound) { + logger(ERROR, BRIGHT_RED) << "Transaction with fee can not have TTL"; + return false; + } else { + fee = 0; + } + + if (!Common::fromString(value, ttl) || ttl < 1 || ttl * 60 > m_currency.mempoolTxLiveTime()) { + logger(ERROR, BRIGHT_RED) << "TTL has invalid format: \"" << value << "\", " << + "enter time from 1 to " << (m_currency.mempoolTxLiveTime() / 60) << " minutes"; + return false; + } } } else { WalletLegacyTransfer destination; @@ -508,6 +542,23 @@ std::string simple_wallet::get_commands_str() { return ss.str(); } +bool simple_wallet::seed(const std::vector &args/* = std::vector()*/) { + std::string electrum_words; + bool success = m_wallet->getSeed(electrum_words); + + if (success) + { + std::cout << "\nPLEASE NOTE: the following 25 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control.\n"; + std::cout << electrum_words << std::endl; + } + else + { + fail_msg_writer() << "The wallet is non-deterministic and doesn't have mnemonic seed."; + } + return true; +} + + bool simple_wallet::help(const std::vector &args/* = std::vector()*/) { success_msg_writer() << get_commands_str(); return true; @@ -530,6 +581,7 @@ simple_wallet::simple_wallet(System::Dispatcher& dispatcher, const CryptoNote::C m_consoleHandler.setHandler("start_mining", boost::bind(&simple_wallet::start_mining, this, _1), "start_mining [] - Start mining in daemon"); m_consoleHandler.setHandler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, _1), "Stop mining in daemon"); //m_consoleHandler.setHandler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance"); + m_consoleHandler.setHandler("export_keys", boost::bind(&simple_wallet::export_keys, this, _1), "Show the secret keys of the opened wallet"); m_consoleHandler.setHandler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance"); m_consoleHandler.setHandler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "Show incoming transfers"); m_consoleHandler.setHandler("list_transfers", boost::bind(&simple_wallet::listTransfers, this, _1), "Show all known transfers"); @@ -541,6 +593,8 @@ simple_wallet::simple_wallet(System::Dispatcher& dispatcher, const CryptoNote::C " is the number of transactions yours is indistinguishable from (from 0 to maximum available)"); m_consoleHandler.setHandler("set_log", boost::bind(&simple_wallet::set_log, this, _1), "set_log - Change current log level, is a number 0-4"); m_consoleHandler.setHandler("address", boost::bind(&simple_wallet::print_address, this, _1), "Show current wallet public address"); + m_consoleHandler.setHandler("show_seed", boost::bind(&simple_wallet::seed, this, _1), "Get wallet recovery phrase (deterministic seed)"); + m_consoleHandler.setHandler("save", boost::bind(&simple_wallet::save, this, _1), "Save wallet synchronized data"); m_consoleHandler.setHandler("reset", boost::bind(&simple_wallet::reset, this, _1), "Discard cache data and start synchronizing from the start"); m_consoleHandler.setHandler("help", boost::bind(&simple_wallet::help, this, _1), "Show this help"); @@ -577,13 +631,13 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) { } if (m_generate_new.empty() && m_wallet_file_arg.empty()) { - std::cout << "Nor 'generate-new-wallet' neither 'wallet-file' argument was specified.\nWhat do you want to do?\n[O]pen existing wallet, [G]enerate new wallet file or [E]xit.\n"; + std::cout << "Nor 'generate-new-wallet' neither 'wallet-file' argument was specified.\nWhat do you want to do?\n[O]pen existing wallet\n[G]enerate new wallet file\n[I]mport wallet from keys\n[M]nemonic seed recover wallet\n[E]xit.\n"; char c; do { std::string answer; std::getline(std::cin, answer); c = answer[0]; - if (!(c == 'O' || c == 'G' || c == 'E' || c == 'o' || c == 'g' || c == 'e')) { + if (!(c == 'O' || c == 'G' || c == 'E' || c == 'I' || c == 'o' || c == 'g' || c == 'e' || c == 'i' || c == 'M')) { std::cout << "Unknown command: " << c <getAddress())) { logger(WARNING, BRIGHT_RED) << "Couldn't write wallet address file: " + walletAddressFile; } + } else if (!m_import_new.empty()) { + std::string walletAddressFile = prepareWalletAddressFilename(m_import_new); + boost::system::error_code ignore; + if (boost::filesystem::exists(walletAddressFile, ignore)) { + logger(ERROR, BRIGHT_RED) << "Address file already exists: " + walletAddressFile; + return false; + } + + std::string private_spend_key_string; + std::string private_view_key_string; + do { + std::cout << "Private Spend Key: "; + std::getline(std::cin, private_spend_key_string); + boost::algorithm::trim(private_spend_key_string); + } while (private_spend_key_string.empty()); + do { + std::cout << "Private View Key: "; + std::getline(std::cin, private_view_key_string); + boost::algorithm::trim(private_view_key_string); + } while (private_view_key_string.empty()); + + Crypto::Hash private_spend_key_hash; + Crypto::Hash private_view_key_hash; + size_t size; + if (!Common::fromHex(private_spend_key_string, &private_spend_key_hash, sizeof(private_spend_key_hash), size) || size != sizeof(private_spend_key_hash)) { + return false; + } + if (!Common::fromHex(private_view_key_string, &private_view_key_hash, sizeof(private_view_key_hash), size) || size != sizeof(private_spend_key_hash)) { + return false; + } + Crypto::SecretKey private_spend_key = *(struct Crypto::SecretKey *) &private_spend_key_hash; + Crypto::SecretKey private_view_key = *(struct Crypto::SecretKey *) &private_view_key_hash; + + if (!new_wallet(private_spend_key, private_view_key, walletFileName, pwd_container.password())) { + logger(ERROR, BRIGHT_RED) << "account creation failed"; + return false; + } } else { m_wallet.reset(new WalletLegacy(m_currency, *m_node)); @@ -718,7 +861,134 @@ void simple_wallet::handle_command_line(const boost::program_options::variables_ m_daemon_address = command_line::get_arg(vm, arg_daemon_address); m_daemon_host = command_line::get_arg(vm, arg_daemon_host); m_daemon_port = command_line::get_arg(vm, arg_daemon_port); + m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet); + m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic); + m_mnemonic_seed = command_line::get_arg(vm, arg_mnemonic_seed); + } + //---------------------------------------------------------------------------------------------------- + bool simple_wallet::gen_wallet(const std::string &wallet_file, const std::string& password, const Crypto::SecretKey& recovery_key, bool recover, bool two_random) { + m_wallet_file = wallet_file; + + m_wallet.reset(new WalletLegacy(m_currency, *m_node.get())); + m_node->addObserver(static_cast(this)); + m_wallet->addObserver(this); + + Crypto::SecretKey recovery_val; + try + { + m_initResultPromise.reset(new std::promise()); + std::future f_initError = m_initResultPromise->get_future(); + + recovery_val = m_wallet->generateKey(password, recovery_key, recover, two_random); + auto initError = f_initError.get(); + m_initResultPromise.reset(nullptr); + if (initError) { + fail_msg_writer() << "failed to generate new wallet: " << initError.message(); + return false; + } + + try { + CryptoNote::WalletHelper::storeWallet(*m_wallet, m_wallet_file); + } catch (std::exception& e) { + fail_msg_writer() << "failed to save new wallet: " << e.what(); + throw; + } + + AccountKeys keys; + m_wallet->getAccountKeys(keys); + + logger(INFO, BRIGHT_WHITE) << + "Generated new wallet: " << m_wallet->getAddress() << std::endl << + "view key: " << Common::podToHex(keys.viewSecretKey); + } + catch (const std::exception& e) { + fail_msg_writer() << "failed to generate new wallet: " << e.what(); + return false; + } + + // convert rng value to electrum-style word list + std::string lang = "English"; + std::string electrum_words; + crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words, lang); + std::string print_electrum = ""; + + success_msg_writer() << + "**********************************************************************\n" << + "Your wallet has been generated.\n" << + "To start synchronizing with the daemon use \"refresh\" command.\n" << + "Use \"help\" command to see the list of available commands.\n" << + "Always use \"exit\" command when closing simplewallet to save\n" << + "current session's state. Otherwise, you will possibly need to synchronize \n" << + "your wallet again. Your wallet key is NOT under risk anyway.\n" + ; + + if (!two_random) + { + std::cout << "\nPLEASE NOTE: the following 25 words can be used to recover access to your wallet. " << + "Please write them down and store them somewhere safe and secure. Please do not store them in your email or " << + "on file storage services outside of your immediate control.\n\n"; + std::cout << electrum_words << std::endl; + } + success_msg_writer() << "**********************************************************************"; + + return true; +} + + +//---------------------------------------------------------------------------------------------------- +bool simple_wallet::new_wallet(Crypto::SecretKey &secret_key, Crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password) { + m_wallet_file = wallet_file; + + m_wallet.reset(new WalletLegacy(m_currency, *m_node.get())); + m_node->addObserver(static_cast(this)); + m_wallet->addObserver(this); + try { + m_initResultPromise.reset(new std::promise()); + std::future f_initError = m_initResultPromise->get_future(); + + AccountKeys wallet_keys; + wallet_keys.spendSecretKey = secret_key; + wallet_keys.viewSecretKey = view_key; + Crypto::secret_key_to_public_key(wallet_keys.spendSecretKey, wallet_keys.address.spendPublicKey); + Crypto::secret_key_to_public_key(wallet_keys.viewSecretKey, wallet_keys.address.viewPublicKey); + + m_wallet->initWithKeys(wallet_keys, password); + auto initError = f_initError.get(); + m_initResultPromise.reset(nullptr); + if (initError) { + fail_msg_writer() << "failed to generate new wallet: " << initError.message(); + return false; + } + + try { + CryptoNote::WalletHelper::storeWallet(*m_wallet, m_wallet_file); + } catch (std::exception& e) { + fail_msg_writer() << "failed to save new wallet: " << e.what(); + throw; + } + + AccountKeys keys; + m_wallet->getAccountKeys(keys); + + logger(INFO, BRIGHT_WHITE) << + "Imported wallet: " << m_wallet->getAddress() << std::endl; + } + catch (const std::exception& e) { + fail_msg_writer() << "failed to import wallet: " << e.what(); + return false; + } + + success_msg_writer() << + "**********************************************************************\n" << + "Your wallet has been imported.\n" << + "Use \"help\" command to see the list of available commands.\n" << + "Always use \"exit\" command when closing simplewallet to save\n" << + "current session's state. Otherwise, you will possibly need to synchronize \n" << + "your wallet again. Your wallet key is NOT under risk anyway.\n" << + "**********************************************************************"; + return true; } + //---------------------------------------------------------------------------------------------------- bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string& password) { m_wallet_file = wallet_file; @@ -729,7 +999,9 @@ bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string try { m_initResultPromise.reset(new std::promise()); std::future f_initError = m_initResultPromise->get_future(); - m_wallet->initAndGenerate(password); + //m_wallet->initAndGenerate(password); + // Create deterministic wallets by default + m_wallet->initAndGenerateDeterministic(password); auto initError = f_initError.get(); m_initResultPromise.reset(nullptr); if (initError) { @@ -746,6 +1018,11 @@ bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string AccountKeys keys; m_wallet->getAccountKeys(keys); + // convert rng value to electrum-style word list + std::string lang = "English"; + std::string electrum_words; + crypto::ElectrumWords::bytes_to_words(keys.spendSecretKey, electrum_words, lang); + std::string print_electrum = ""; logger(INFO, BRIGHT_WHITE) << "Generated new wallet: " << m_wallet->getAddress() << std::endl << @@ -764,6 +1041,12 @@ bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string "current session's state. Otherwise, you will possibly need to synchronize \n" << "your wallet again. Your wallet key is NOT under risk anyway.\n" << "**********************************************************************"; + + std::cout << "\nPLEASE NOTE: the following 25 words can be used to recover access to your wallet. " << + "Please write them down and store them somewhere safe and secure. Please do not store them in your email or " << + "on file storage services outside of your immediate control.\n\n"; + //std::cout << electrum_words << std::endl; + success_msg_writer() << "**********************************************************************"; return true; } //---------------------------------------------------------------------------------------------------- @@ -944,6 +1227,19 @@ bool simple_wallet::show_balance(const std::vector& args/* = std::v return true; } + +//---------------------------------------------------------------------------------------------------- + bool simple_wallet::export_keys(const std::vector& args/* = std::vector()*/) { + AccountKeys keys; + m_wallet->getAccountKeys(keys); + std::cout << "Spend secret key: " << Common::podToHex(keys.spendSecretKey) << std::endl; + std::cout << "View secret key: " << Common::podToHex(keys.viewSecretKey) << std::endl; + std::cout << "Private keys: " << Tools::Base58::encode_addr(parameters::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX, + std::string(reinterpret_cast(&keys), sizeof(keys))) << std::endl; + + return true; + } + //---------------------------------------------------------------------------------------------------- bool simple_wallet::show_incoming_transfers(const std::vector& args) { bool hasTransfers = false; @@ -1113,6 +1409,18 @@ bool simple_wallet::transfer(const std::vector &args) { } } + std::vector messages; + for (auto dst : cmd.dsts) { + for (auto msg : cmd.messages) { + messages.emplace_back(TransactionMessage{ msg, dst.address }); + } + } + + uint64_t ttl = 0; + if (cmd.ttl != 0) { + ttl = static_cast(time(nullptr)) + cmd.ttl; + } + CryptoNote::WalletHelper::SendCompleteResultObserver sent; std::string extraString; @@ -1120,7 +1428,7 @@ bool simple_wallet::transfer(const std::vector &args) { WalletHelper::IWalletRemoveObserverGuard removeGuard(*m_wallet, sent); - CryptoNote::TransactionId tx = m_wallet->sendTransaction(cmd.dsts, cmd.fee, extraString, cmd.fake_outs_count, 0); + CryptoNote::TransactionId tx = m_wallet->sendTransaction(cmd.dsts, cmd.fee, extraString, cmd.fake_outs_count, 0, messages, ttl); if (tx == WALLET_LEGACY_INVALID_TRANSACTION_ID) { fail_msg_writer() << "Can't send money"; return true; @@ -1200,6 +1508,9 @@ int main(int argc, char* argv[]) { po::options_description desc_params("Wallet options"); command_line::add_arg(desc_params, arg_wallet_file); command_line::add_arg(desc_params, arg_generate_new_wallet); + command_line::add_arg(desc_params, arg_restore_deterministic_wallet); + command_line::add_arg(desc_params, arg_non_deterministic); + command_line::add_arg(desc_params, arg_mnemonic_seed); command_line::add_arg(desc_params, arg_password); command_line::add_arg(desc_params, arg_daemon_address); command_line::add_arg(desc_params, arg_daemon_host); diff --git a/src/SimpleWallet/SimpleWallet.h b/src/SimpleWallet/SimpleWallet.h index a6fdda4..8fd05c0 100644 --- a/src/SimpleWallet/SimpleWallet.h +++ b/src/SimpleWallet/SimpleWallet.h @@ -20,6 +20,7 @@ #include "CryptoNoteCore/Currency.h" #include "NodeRpcProxy/NodeRpcProxy.h" #include "WalletLegacy/WalletHelper.h" +#include "WalletLegacy/WalletLegacy.h" #include #include @@ -63,14 +64,18 @@ namespace CryptoNote bool run_console_handler(); bool new_wallet(const std::string &wallet_file, const std::string& password); + bool new_wallet(Crypto::SecretKey &secret_key, Crypto::SecretKey &view_key, const std::string &wallet_file, const std::string& password); + bool gen_wallet(const std::string &wallet_file, const std::string& password, const Crypto::SecretKey& recovery_key = Crypto::SecretKey(), bool recover = false, bool two_random = false); bool open_wallet(const std::string &wallet_file, const std::string& password); bool close_wallet(); bool help(const std::vector &args = std::vector()); + bool seed(const std::vector &args = std::vector()); bool exit(const std::vector &args); bool start_mining(const std::vector &args); bool stop_mining(const std::vector &args); bool show_balance(const std::vector &args = std::vector()); + bool export_keys(const std::vector &args = std::vector()); bool show_incoming_transfers(const std::vector &args); bool show_payments(const std::vector &args); bool show_blockchain_height(const std::vector &args); @@ -143,14 +148,20 @@ namespace CryptoNote private: std::string m_wallet_file_arg; std::string m_generate_new; + std::string m_import_new; std::string m_import_path; std::string m_daemon_address; std::string m_daemon_host; + std::string m_mnemonic_seed; uint16_t m_daemon_port; std::string m_wallet_file; + + Crypto::SecretKey m_recovery_key; // recovery key (used as random for wallet gen) + bool m_restore_deterministic_wallet; // recover flag + bool m_non_deterministic; // old 2-random generation std::unique_ptr> m_initResultPromise; Common::ConsoleHandler m_consoleHandler; diff --git a/src/Transfers/TransfersConsumer.cpp b/src/Transfers/TransfersConsumer.cpp index 03c2392..67e13ab 100644 --- a/src/Transfers/TransfersConsumer.cpp +++ b/src/Transfers/TransfersConsumer.cpp @@ -6,8 +6,10 @@ #include "TransfersConsumer.h" #include +#include #include "CommonTypes.h" +#include "Common/StringTools.h" #include "Common/BlockingQueue.h" #include "CryptoNoteCore/CryptoNoteFormatUtils.h" #include "CryptoNoteCore/TransactionApi.h" @@ -15,9 +17,15 @@ #include "IWallet.h" #include "INode.h" -#include + using namespace Crypto; +using namespace Logging; +using namespace Common; + +std::unordered_set transactions_hash_seen; +std::unordered_set public_keys_seen; +std::mutex seen_mutex; namespace { @@ -76,7 +84,7 @@ void findMyOutputs( for (const auto& key : out.keys) { checkOutputKey(derivation, key, idx, idx, spendKeys, outputs); ++keyIndex; - } + } } } } @@ -351,6 +359,12 @@ void TransfersConsumer::removeUnconfirmedTransaction(const Crypto::Hash& transac m_observerManager.notify(&IBlockchainConsumerObserver::onTransactionDeleteEnd, this, transactionHash); } +void TransfersConsumer::addPublicKeysSeen(const Crypto::Hash& transactionHash, const Crypto::PublicKey& outputKey) { + std::lock_guard lk(seen_mutex); + transactions_hash_seen.insert(transactionHash); + public_keys_seen.insert(outputKey); +} + std::error_code createTransfers( const AccountKeys& account, const TransactionBlockInfo& blockInfo, @@ -360,6 +374,9 @@ std::error_code createTransfers( std::vector& transfers) { auto txPubKey = tx.getTransactionPublicKey(); + auto txHash = tx.getTransactionHash(); + std::vector temp_keys; + std::lock_guard lk(seen_mutex); for (auto idx : outputs) { @@ -398,6 +415,17 @@ std::error_code createTransfers( assert(out.key == reinterpret_cast(in_ephemeral.publicKey)); + std::unordered_set::iterator it = transactions_hash_seen.find(tx.getTransactionHash()); + if (it == transactions_hash_seen.end()) { + std::unordered_set::iterator key_it = public_keys_seen.find(out.key); + if (key_it != public_keys_seen.end()) { + throw std::runtime_error("duplicate transaction output key is found"); + return std::error_code(); + } + temp_keys.push_back(out.key); + } + + info.amount = amount; info.outputKey = out.key; @@ -405,22 +433,48 @@ std::error_code createTransfers( uint64_t amount; MultisignatureOutput out; tx.getOutput(idx, out, amount); - + + for (const auto& key : out.keys) { + std::unordered_set::iterator it = transactions_hash_seen.find(txHash); + if (it == transactions_hash_seen.end()) { + std::unordered_set::iterator key_it = public_keys_seen.find(key); + if (key_it != public_keys_seen.end()) { + // m_logger(ERROR, BRIGHT_RED) << "Failed to process transaction " << Common::podToHex(txHash) << ": duplicate multisignature output key is found"; + return std::error_code(); + } + if (std::find(temp_keys.begin(), temp_keys.end(), key) != temp_keys.end()) { + // m_logger(ERROR, BRIGHT_RED) << "Failed to process transaction " << Common::podToHex(txHash) << ": the same multisignature output key is present more than once"; + return std::error_code(); + } + temp_keys.push_back(key); + } + } info.amount = amount; info.requiredSignatures = out.requiredSignatureCount; info.term = out.term; } - - transfers.push_back(info); + + transfers.push_back(info); } + transactions_hash_seen.emplace(tx.getTransactionHash()); + std::copy(temp_keys.begin(), temp_keys.end(), std::inserter(public_keys_seen, public_keys_seen.end())); + + + return std::error_code(); } std::error_code TransfersConsumer::preprocessOutputs(const TransactionBlockInfo& blockInfo, const ITransactionReader& tx, PreprocessInfo& info) { std::unordered_map> outputs; - findMyOutputs(tx, m_viewSecret, m_spendKeys, outputs); - + try { + findMyOutputs(tx, m_viewSecret, m_spendKeys, outputs); + } + catch (const std::exception& e) { + // m_logger(ERROR, BRIGHT_RED) << "Failed to process transaction: " << e.what() << ", transaction hash " << Common::podToHex(tx.getTransactionHash()); + return std::error_code(); + } + if (outputs.empty()) { return std::error_code(); } @@ -438,10 +492,16 @@ std::error_code TransfersConsumer::preprocessOutputs(const TransactionBlockInfo& auto it = m_subscriptions.find(kv.first); if (it != m_subscriptions.end()) { auto& transfers = info.outputs[kv.first]; - errorCode = createTransfers(it->second->getKeys(), blockInfo, tx, kv.second, info.globalIdxs, transfers); - if (errorCode) { - return errorCode; - } + try { + errorCode = createTransfers(it->second->getKeys(), blockInfo, tx, kv.second, info.globalIdxs, transfers); + if (errorCode) { + return errorCode; + } + } + catch (const std::exception& e) { + // m_logger(ERROR, BRIGHT_RED) << "Failed to process transaction: " << e.what() << ", transaction hash " << Common::podToHex(tx.getTransactionHash()); + return std::error_code(); + } } } diff --git a/src/Transfers/TransfersConsumer.h b/src/Transfers/TransfersConsumer.h index e828968..269aa95 100644 --- a/src/Transfers/TransfersConsumer.h +++ b/src/Transfers/TransfersConsumer.h @@ -32,6 +32,7 @@ class TransfersConsumer: public IObservableImpl& subscriptions); void initTransactionPool(const std::unordered_set& uncommitedTransactions); + void addPublicKeysSeen(const Crypto::Hash& transactionHash, const Crypto::PublicKey& outputKey); // IBlockchainConsumer virtual SynchronizationStart getSyncStart() override; diff --git a/src/Transfers/TransfersSynchronizer.cpp b/src/Transfers/TransfersSynchronizer.cpp index 77ba161..1b2bb63 100644 --- a/src/Transfers/TransfersSynchronizer.cpp +++ b/src/Transfers/TransfersSynchronizer.cpp @@ -76,6 +76,13 @@ ITransfersSubscription* TransfersSyncronizer::getSubscription(const AccountPubli return (it == m_consumers.end()) ? nullptr : it->second->getSubscription(acc); } +void TransfersSyncronizer::addPublicKeysSeen(const AccountPublicAddress& acc, const Crypto::Hash& transactionHash, const Crypto::PublicKey& outputKey) { + auto it = m_consumers.find(acc.viewPublicKey); + if (it != m_consumers.end()) { + it->second->addPublicKeysSeen(transactionHash, outputKey); + } +} + std::vector TransfersSyncronizer::getViewKeyKnownBlocks(const Crypto::PublicKey& publicViewKey) { auto it = m_consumers.find(publicViewKey); if (it == m_consumers.end()) { diff --git a/src/Transfers/TransfersSynchronizer.h b/src/Transfers/TransfersSynchronizer.h index 7d6a2d1..d98ff4f 100644 --- a/src/Transfers/TransfersSynchronizer.h +++ b/src/Transfers/TransfersSynchronizer.h @@ -40,6 +40,8 @@ class TransfersSyncronizer : public ITransfersSynchronizer, public IBlockchainCo void subscribeConsumerNotifications(const Crypto::PublicKey& viewPublicKey, ITransfersSynchronizerObserver* observer); void unsubscribeConsumerNotifications(const Crypto::PublicKey& viewPublicKey, ITransfersSynchronizerObserver* observer); + void addPublicKeysSeen(const AccountPublicAddress& acc, const Crypto::Hash& transactionHash, const Crypto::PublicKey& outputKey); + // IStreamSerializable virtual void save(std::ostream& os) override; virtual void load(std::istream& in) override; diff --git a/src/Wallet/WalletGreen.cpp b/src/Wallet/WalletGreen.cpp index 41fda0e..40fa4ac 100644 --- a/src/Wallet/WalletGreen.cpp +++ b/src/Wallet/WalletGreen.cpp @@ -489,13 +489,14 @@ std::string WalletGreen::createAddress() { return doCreateAddress(spendKey.publicKey, spendKey.secretKey, creationTimestamp); } -std::string WalletGreen::createAddress(const Crypto::SecretKey& spendSecretKey) { +std::string WalletGreen::createAddress(const Crypto::SecretKey& spendSecretKey, bool reset) { Crypto::PublicKey spendPublicKey; if (!Crypto::secret_key_to_public_key(spendSecretKey, spendPublicKey) ) { throw std::system_error(make_error_code(CryptoNote::error::KEY_GENERATION_ERROR)); } - return doCreateAddress(spendPublicKey, spendSecretKey, 0); + uint64_t creationTimestamp = reset ? 0 : static_cast(time(nullptr)); + return doCreateAddress(spendPublicKey, spendSecretKey, creationTimestamp); } std::string WalletGreen::createAddress(const Crypto::PublicKey& spendPublicKey) { diff --git a/src/Wallet/WalletGreen.h b/src/Wallet/WalletGreen.h index 239b552..e4d4a8d 100644 --- a/src/Wallet/WalletGreen.h +++ b/src/Wallet/WalletGreen.h @@ -43,7 +43,7 @@ class WalletGreen : public IWallet, virtual KeyPair getAddressSpendKey(const std::string& address) const override; virtual KeyPair getViewKey() const override; virtual std::string createAddress() override; - virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey) override; + virtual std::string createAddress(const Crypto::SecretKey& spendSecretKey, bool reset = true) override; virtual std::string createAddress(const Crypto::PublicKey& spendPublicKey) override; virtual void deleteAddress(const std::string& address) override; diff --git a/src/Wallet/WalletRpcServer.cpp b/src/Wallet/WalletRpcServer.cpp index b32adfc..80b0afc 100644 --- a/src/Wallet/WalletRpcServer.cpp +++ b/src/Wallet/WalletRpcServer.cpp @@ -24,10 +24,14 @@ namespace Tools { const command_line::arg_descriptor wallet_rpc_server::arg_rpc_bind_port = { "rpc-bind-port", "Starts wallet as rpc server for wallet operations, sets bind port for server", 0, true }; const command_line::arg_descriptor wallet_rpc_server::arg_rpc_bind_ip = { "rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1" }; +const command_line::arg_descriptor wallet_rpc_server::arg_rpc_user = { "rpc-user", "Username to use the rpc server. If authorization is not required, leave it empty", "" }; +const command_line::arg_descriptor wallet_rpc_server::arg_rpc_password = { "rpc-password", "Password to use the rpc server. If authorization is not required, leave it empty", "" }; void wallet_rpc_server::init_options(boost::program_options::options_description& desc) { command_line::add_arg(desc, arg_rpc_bind_ip); command_line::add_arg(desc, arg_rpc_bind_port); + command_line::add_arg(desc, arg_rpc_user); + command_line::add_arg(desc, arg_rpc_password); } //------------------------------------------------------------------------------------------------------------------------------ wallet_rpc_server::wallet_rpc_server( @@ -49,7 +53,7 @@ wallet_rpc_server::wallet_rpc_server( } //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::run() { - start(m_bind_ip, m_port); + start(m_bind_ip, m_port, m_rpcUser, m_rpcPassword); m_stopComplete.wait(); return true; } @@ -66,6 +70,8 @@ void wallet_rpc_server::send_stop_signal() { bool wallet_rpc_server::handle_command_line(const boost::program_options::variables_map& vm) { m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip); m_port = command_line::get_arg(vm, arg_rpc_bind_port); + m_rpcUser = command_line::get_arg(vm, arg_rpc_user); + m_rpcPassword = command_line::get_arg(vm, arg_rpc_password); return true; } //------------------------------------------------------------------------------------------------------------------------------ @@ -93,6 +99,7 @@ void wallet_rpc_server::processRequest(const CryptoNote::HttpRequest& request, C { "getbalance", makeMemberMethod(&wallet_rpc_server::on_getbalance) }, { "transfer", makeMemberMethod(&wallet_rpc_server::on_transfer) }, { "store", makeMemberMethod(&wallet_rpc_server::on_store) }, + { "get_messages", makeMemberMethod(&wallet_rpc_server::on_get_messages) }, { "get_payments", makeMemberMethod(&wallet_rpc_server::on_get_payments) }, { "get_transfers", makeMemberMethod(&wallet_rpc_server::on_get_transfers) }, { "get_height", makeMemberMethod(&wallet_rpc_server::on_get_height) }, @@ -126,11 +133,16 @@ bool wallet_rpc_server::on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE: //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res) { std::vector transfers; + std::vector messages; for (auto it = req.destinations.begin(); it != req.destinations.end(); it++) { CryptoNote::WalletLegacyTransfer transfer; transfer.address = it->address; transfer.amount = it->amount; transfers.push_back(transfer); + + if (!it->message.empty()) { + messages.emplace_back(CryptoNote::TransactionMessage{ it->message, it->address }); + } } std::vector extra; @@ -151,18 +163,22 @@ bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::requ } } - std::vector messages; for (auto& rpc_message : req.messages) { messages.emplace_back(CryptoNote::TransactionMessage{ rpc_message.message, rpc_message.address }); } + uint64_t ttl = 0; + if (req.ttl != 0) { + ttl = static_cast(time(nullptr)) + req.ttl; + } + std::string extraString; std::copy(extra.begin(), extra.end(), std::back_inserter(extraString)); try { CryptoNote::WalletHelper::SendCompleteResultObserver sent; WalletHelper::IWalletRemoveObserverGuard removeGuard(m_wallet, sent); - CryptoNote::TransactionId tx = m_wallet.sendTransaction(transfers, req.fee, extraString, req.mixin, req.unlock_time, messages); + CryptoNote::TransactionId tx = m_wallet.sendTransaction(transfers, req.fee, extraString, req.mixin, req.unlock_time, messages, ttl); if (tx == WALLET_LEGACY_INVALID_TRANSACTION_ID) { throw std::runtime_error("Couldn't send transaction"); } @@ -194,6 +210,30 @@ bool wallet_rpc_server::on_store(const wallet_rpc::COMMAND_RPC_STORE::request& r return true; } //------------------------------------------------------------------------------------------------------------------------------ +bool wallet_rpc_server::on_get_messages(const wallet_rpc::COMMAND_RPC_GET_MESSAGES::request& req, wallet_rpc::COMMAND_RPC_GET_MESSAGES::response& res) { + res.total_tx_count = m_wallet.getTransactionCount(); + + for (uint64_t i = req.first_tx_id; i < res.total_tx_count && res.tx_messages.size() < req.tx_limit; ++i) { + WalletLegacyTransaction tx; + if (!m_wallet.getTransaction(static_cast(i), tx)) { + throw JsonRpc::JsonRpcError(WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR, "Failed to get transaction"); + } + + if (!tx.messages.empty()) { + wallet_rpc::transaction_messages tx_messages; + tx_messages.tx_hash = Common::podToHex(tx.hash); + tx_messages.tx_id = i; + tx_messages.block_height = tx.blockHeight; + tx_messages.timestamp = tx.timestamp; + std::copy(tx.messages.begin(), tx.messages.end(), std::back_inserter(tx_messages.messages)); + + res.tx_messages.emplace_back(std::move(tx_messages)); + } + } + + return true; +} +//------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res) { PaymentId expectedPaymentId; CryptoNote::BinaryArray payment_id_blob; diff --git a/src/Wallet/WalletRpcServer.h b/src/Wallet/WalletRpcServer.h index ef35a07..a9aed7d 100644 --- a/src/Wallet/WalletRpcServer.h +++ b/src/Wallet/WalletRpcServer.h @@ -41,6 +41,8 @@ namespace Tools static const command_line::arg_descriptor arg_rpc_bind_port; static const command_line::arg_descriptor arg_rpc_bind_ip; + static const command_line::arg_descriptor arg_rpc_user; + static const command_line::arg_descriptor arg_rpc_password; private: @@ -50,6 +52,7 @@ namespace Tools bool on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res); bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res); bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res); + bool on_get_messages(const wallet_rpc::COMMAND_RPC_GET_MESSAGES::request& req, wallet_rpc::COMMAND_RPC_GET_MESSAGES::response& res); bool on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res); bool on_get_transfers(const wallet_rpc::COMMAND_RPC_GET_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_GET_TRANSFERS::response& res); bool on_get_height(const wallet_rpc::COMMAND_RPC_GET_HEIGHT::request& req, wallet_rpc::COMMAND_RPC_GET_HEIGHT::response& res); @@ -62,6 +65,8 @@ namespace Tools CryptoNote::INode& m_node; uint16_t m_port; std::string m_bind_ip; + std::string m_rpcUser; + std::string m_rpcPassword; CryptoNote::Currency& m_currency; const std::string m_walletFilename; diff --git a/src/Wallet/WalletRpcServerCommandsDefinitions.h b/src/Wallet/WalletRpcServerCommandsDefinitions.h index e0df18e..9b907fd 100644 --- a/src/Wallet/WalletRpcServerCommandsDefinitions.h +++ b/src/Wallet/WalletRpcServerCommandsDefinitions.h @@ -44,10 +44,12 @@ using CryptoNote::ISerializer; { uint64_t amount; std::string address; + std::string message; void serialize(ISerializer& s) { KV_MEMBER(amount) KV_MEMBER(address) + KV_MEMBER(message) } }; @@ -71,6 +73,7 @@ using CryptoNote::ISerializer; uint64_t unlock_time; std::string payment_id; std::list messages; + uint64_t ttl = 0; void serialize(ISerializer& s) { KV_MEMBER(destinations) @@ -79,6 +82,7 @@ using CryptoNote::ISerializer; KV_MEMBER(unlock_time) KV_MEMBER(payment_id) KV_MEMBER(messages) + KV_MEMBER(ttl) } }; @@ -98,6 +102,44 @@ using CryptoNote::ISerializer; typedef CryptoNote::EMPTY_STRUCT response; }; + struct transaction_messages { + std::string tx_hash; + uint64_t tx_id; + uint32_t block_height; + uint64_t timestamp; + std::list messages; + + void serialize(ISerializer& s) { + KV_MEMBER(tx_hash); + KV_MEMBER(tx_id); + KV_MEMBER(block_height); + KV_MEMBER(timestamp); + KV_MEMBER(messages); + } + }; + + struct COMMAND_RPC_GET_MESSAGES { + struct request { + uint64_t first_tx_id = 0; + uint32_t tx_limit = std::numeric_limits::max(); + + void serialize(ISerializer& s) { + KV_MEMBER(first_tx_id); + KV_MEMBER(tx_limit); + } + }; + + struct response { + uint64_t total_tx_count; + std::list tx_messages; + + void serialize(ISerializer& s) { + KV_MEMBER(total_tx_count); + KV_MEMBER(tx_messages); + } + }; + }; + struct payment_details { std::string tx_hash; diff --git a/src/WalletLegacy/WalletLegacy.cpp b/src/WalletLegacy/WalletLegacy.cpp index b6f9984..db0ff85 100644 --- a/src/WalletLegacy/WalletLegacy.cpp +++ b/src/WalletLegacy/WalletLegacy.cpp @@ -14,6 +14,16 @@ #include "WalletLegacy/WalletLegacySerializer.h" #include "WalletLegacy/WalletUtils.h" +#include "CryptoNoteConfig.h" + +#include "Mnemonics/electrum-words.h" + + extern "C" + { + #include "crypto/keccak.h" + #include "crypto/crypto-ops.h" + } + using namespace Crypto; namespace { @@ -76,7 +86,7 @@ class SaveWaiter : public CryptoNote::IWalletLegacyObserver { uint64_t calculateDepositsAmount(const std::vector& transfers, const CryptoNote::Currency& currency) { return std::accumulate(transfers.begin(), transfers.end(), static_cast(0), [¤cy] (uint64_t sum, const CryptoNote::TransactionOutputInformation& deposit) { - return sum + deposit.amount + currency.calculateInterest(deposit.amount, deposit.term); + return sum + deposit.amount + currency.calculateInterest(deposit.amount, deposit.term, 4294967294ULL); }); } @@ -151,6 +161,7 @@ void WalletLegacy::initAndGenerate(const std::string& password) { } m_account.generate(); + m_account.generateDeterministic(); m_password = password; initSync(); @@ -159,6 +170,42 @@ void WalletLegacy::initAndGenerate(const std::string& password) { m_observerManager.notify(&IWalletLegacyObserver::initCompleted, std::error_code()); } +Crypto::SecretKey WalletLegacy::generateKey(const std::string& password, const Crypto::SecretKey& recovery_param, bool recover, bool two_random) { + std::unique_lock stateLock(m_cacheMutex); + + if (m_state != NOT_INITIALIZED) { + throw std::system_error(make_error_code(error::ALREADY_INITIALIZED)); + } + + Crypto::SecretKey retval = m_account.generate_key(recovery_param, recover, two_random); + m_password = password; + + initSync(); + + m_observerManager.notify(&IWalletLegacyObserver::initCompleted, std::error_code()); + return retval; +} + +void WalletLegacy::initAndGenerateDeterministic(const std::string& password) { + { + std::unique_lock stateLock(m_cacheMutex); + + if (m_state != NOT_INITIALIZED) { + throw std::system_error(make_error_code(error::ALREADY_INITIALIZED)); + } + + m_account.generateDeterministic(); + m_password = password; + + initSync(); + } + + m_observerManager.notify(&IWalletLegacyObserver::initCompleted, std::error_code()); +} + + + + void WalletLegacy::initWithKeys(const AccountKeys& accountKeys, const std::string& password) { { std::unique_lock stateLock(m_cacheMutex); @@ -177,6 +224,19 @@ void WalletLegacy::initWithKeys(const AccountKeys& accountKeys, const std::strin m_observerManager.notify(&IWalletLegacyObserver::initCompleted, std::error_code()); } +bool WalletLegacy::getSeed(std::string& electrum_words) +{ + std::string lang = "English"; + crypto::ElectrumWords::bytes_to_words(m_account.getAccountKeys().spendSecretKey, electrum_words, lang); + + Crypto::SecretKey second; + keccak((uint8_t *)&m_account.getAccountKeys().spendSecretKey, sizeof(Crypto::SecretKey), (uint8_t *)&second, sizeof(Crypto::SecretKey)); + + sc_reduce32((uint8_t *)&second); + + return memcmp(second.data, m_account.getAccountKeys().viewSecretKey.data, sizeof(Crypto::SecretKey)) == 0; +} + void WalletLegacy::initAndLoad(std::istream& source, const std::string& password) { std::unique_lock stateLock(m_cacheMutex); @@ -228,6 +288,16 @@ void WalletLegacy::doLoad(std::istream& source) { } catch (const std::exception&) { // ignore cache loading errors } + // Read all output keys cache + std::vector allTransfers; + m_transferDetails->getOutputs(allTransfers, ITransfersContainer::IncludeAll); + std::cout << "Loaded " + std::to_string(allTransfers.size()) + " known transfer(s)\r\n"; + for (auto& o : allTransfers) { + if (o.type == TransactionTypes::OutputType::Key) { + m_transfersSync.addPublicKeysSeen(m_account.getAccountKeys().address, o.transactionHash, o.outputKey); + } + } + } catch (std::system_error& e) { runAtomic(m_cacheMutex, [this] () {this->m_state = WalletLegacy::NOT_INITIALIZED;} ); m_observerManager.notify(&IWalletLegacyObserver::initCompleted, e.code()); @@ -464,12 +534,13 @@ TransactionId WalletLegacy::sendTransaction(const WalletLegacyTransfer& transfer const std::string& extra, uint64_t mixIn, uint64_t unlockTimestamp, - const std::vector& messages) { + const std::vector& messages, + uint64_t ttl) { std::vector transfers; transfers.push_back(transfer); throwIfNotInitialised(); - return sendTransaction(transfers, fee, extra, mixIn, unlockTimestamp, messages); + return sendTransaction(transfers, fee, extra, mixIn, unlockTimestamp, messages, ttl); } TransactionId WalletLegacy::sendTransaction(const std::vector& transfers, @@ -477,7 +548,8 @@ TransactionId WalletLegacy::sendTransaction(const std::vector& messages) { + const std::vector& messages, + uint64_t ttl) { TransactionId txId = 0; std::unique_ptr request; std::deque> events; @@ -485,7 +557,7 @@ TransactionId WalletLegacy::sendTransaction(const std::vector lock(m_cacheMutex); - request = m_sender->makeSendRequest(txId, events, transfers, fee, extra, mixIn, unlockTimestamp, messages); + request = m_sender->makeSendRequest(txId, events, transfers, fee, extra, mixIn, unlockTimestamp, messages, ttl); } notifyClients(events); diff --git a/src/WalletLegacy/WalletLegacy.h b/src/WalletLegacy/WalletLegacy.h index 4723139..5bd71d7 100644 --- a/src/WalletLegacy/WalletLegacy.h +++ b/src/WalletLegacy/WalletLegacy.h @@ -45,11 +45,14 @@ class WalletLegacy : virtual void removeObserver(IWalletLegacyObserver* observer) override; virtual void initAndGenerate(const std::string& password) override; + virtual void initAndGenerateDeterministic(const std::string& password) override; virtual void initAndLoad(std::istream& source, const std::string& password) override; virtual void initWithKeys(const AccountKeys& accountKeys, const std::string& password) override; virtual void shutdown() override; virtual void reset() override; + Crypto::SecretKey generateKey(const std::string& password, const Crypto::SecretKey& recovery_param = Crypto::SecretKey(), bool recover = false, bool two_random = false); + virtual void save(std::ostream& destination, bool saveDetailed = true, bool saveCache = true) override; virtual std::error_code changePassword(const std::string& oldPassword, const std::string& newPassword) override; @@ -77,19 +80,24 @@ class WalletLegacy : const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, - const std::vector& messages = std::vector()) override; + const std::vector& messages = std::vector(), + uint64_t ttl = 0) override; virtual TransactionId sendTransaction(const std::vector& transfers, uint64_t fee, const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, - const std::vector& messages = std::vector()) override; + const std::vector& messages = std::vector(), + uint64_t ttl = 0) override; virtual TransactionId deposit(uint32_t term, uint64_t amount, uint64_t fee, uint64_t mixIn = 0) override; virtual TransactionId withdrawDeposits(const std::vector& depositIds, uint64_t fee) override; virtual std::error_code cancelTransaction(size_t transactionId) override; virtual void getAccountKeys(AccountKeys& keys) override; + bool getSeed(std::string& electrum_words); + + private: // IBlockchainSynchronizerObserver diff --git a/src/WalletLegacy/WalletSendTransactionContext.h b/src/WalletLegacy/WalletSendTransactionContext.h index 1c0ea81..2d9131c 100644 --- a/src/WalletLegacy/WalletSendTransactionContext.h +++ b/src/WalletLegacy/WalletSendTransactionContext.h @@ -33,6 +33,7 @@ struct SendTransactionContext TxDustPolicy dustPolicy; uint64_t mixIn; std::vector messages; + uint64_t ttl; uint32_t depositTerm; }; diff --git a/src/WalletLegacy/WalletTransactionSender.cpp b/src/WalletLegacy/WalletTransactionSender.cpp index 9e1815e..20e742e 100644 --- a/src/WalletLegacy/WalletTransactionSender.cpp +++ b/src/WalletLegacy/WalletTransactionSender.cpp @@ -51,13 +51,13 @@ void createChangeDestinations(const AccountPublicAddress& address, uint64_t need } void constructTx(const AccountKeys keys, const std::vector& sources, const std::vector& splittedDests, - const std::string& extra, uint64_t unlockTimestamp, uint64_t sizeLimit, Transaction& tx, const std::vector& messages) { + const std::string& extra, uint64_t unlockTimestamp, uint64_t sizeLimit, Transaction& tx, const std::vector& messages, uint64_t ttl) { std::vector extraVec; extraVec.reserve(extra.size()); std::for_each(extra.begin(), extra.end(), [&extraVec] (const char el) { extraVec.push_back(el);}); Logging::LoggerGroup nullLog; - bool r = constructTransaction(keys, sources, splittedDests, messages, extraVec, tx, unlockTimestamp, nullLog); + bool r = constructTransaction(keys, sources, splittedDests, messages, ttl, extraVec, tx, unlockTimestamp, nullLog); throwIf(!r, error::INTERNAL_WALLET_ERROR); throwIf(getObjectBinarySize(tx) >= sizeLimit, error::TRANSACTION_SIZE_TOO_BIG); @@ -181,7 +181,8 @@ std::unique_ptr WalletTransactionSender::makeSendRequest(Transact const std::string& extra, uint64_t mixIn, uint64_t unlockTimestamp, - const std::vector& messages) { + const std::vector& messages, + uint64_t ttl) { throwIf(transfers.empty(), error::ZERO_DESTINATION); validateTransfersAddresses(transfers); uint64_t neededMoney = countNeededMoney(fee, transfers); @@ -194,6 +195,7 @@ std::unique_ptr WalletTransactionSender::makeSendRequest(Transact transactionId = m_transactionsCache.addNewTransaction(neededMoney, fee, extra, transfers, unlockTimestamp, messages); context->transactionId = transactionId; context->mixIn = mixIn; + context->ttl = ttl; for (const TransactionMessage& message : messages) { AccountPublicAddress address; @@ -331,7 +333,7 @@ std::unique_ptr WalletTransactionSender::doSendTransaction(std::s splitDestinations(transaction.firstTransferId, transaction.transferCount, changeDts, context->dustPolicy, splittedDests); Transaction tx; - constructTx(m_keys, sources, splittedDests, transaction.extra, transaction.unlockTime, m_upperTransactionSizeLimit, tx, context->messages); + constructTx(m_keys, sources, splittedDests, transaction.extra, transaction.unlockTime, m_upperTransactionSizeLimit, tx, context->messages, context->ttl); getObjectHash(tx, transaction.hash); @@ -399,7 +401,7 @@ std::unique_ptr WalletTransactionSender::doSendMultisigTransactio deposit.term = context->depositTerm; deposit.creatingTransactionId = context->transactionId; deposit.spendingTransactionId = WALLET_LEGACY_INVALID_TRANSACTION_ID; - deposit.interest = m_currency.calculateInterest(deposit.amount, deposit.term); + deposit.interest = m_currency.calculateInterest(deposit.amount, deposit.term, transactionInfo.blockHeight); deposit.locked = true; DepositId depositId = m_transactionsCache.insertDeposit(deposit, depositIndex, transaction->getTransactionHash()); transactionInfo.firstDepositId = depositId; diff --git a/src/WalletLegacy/WalletTransactionSender.h b/src/WalletLegacy/WalletTransactionSender.h index 0eacf39..6367060 100644 --- a/src/WalletLegacy/WalletTransactionSender.h +++ b/src/WalletLegacy/WalletTransactionSender.h @@ -32,7 +32,8 @@ class WalletTransactionSender const std::string& extra = "", uint64_t mixIn = 0, uint64_t unlockTimestamp = 0, - const std::vector& messages = std::vector()); + const std::vector& messages = std::vector(), + uint64_t ttl = 0); std::unique_ptr makeDepositRequest(TransactionId& transactionId, std::deque>& events, diff --git a/src/WalletLegacy/WalletUserTransactionsCache.cpp b/src/WalletLegacy/WalletUserTransactionsCache.cpp index 116d654..11fa4d9 100644 --- a/src/WalletLegacy/WalletUserTransactionsCache.cpp +++ b/src/WalletLegacy/WalletUserTransactionsCache.cpp @@ -604,12 +604,14 @@ DepositId WalletUserTransactionsCache::insertNewDeposit(const TransactionOutputI assert(depositOutput.term != 0); assert(m_transactionOutputToDepositIndex.find(std::tie(depositOutput.transactionHash, depositOutput.outputInTransaction)) == m_transactionOutputToDepositIndex.end()); + WalletLegacyTransaction& transactionInfo = getTransaction(creatingTransactionId); + Deposit deposit; deposit.amount = depositOutput.amount; deposit.creatingTransactionId = creatingTransactionId; deposit.term = depositOutput.term; deposit.spendingTransactionId = WALLET_LEGACY_INVALID_TRANSACTION_ID; - deposit.interest = currency.calculateInterest(deposit.amount, deposit.term); + deposit.interest = currency.calculateInterest(deposit.amount, deposit.term, transactionInfo.blockHeight); deposit.locked = true; return insertDeposit(deposit, depositOutput.outputInTransaction, depositOutput.transactionHash); diff --git a/src/crypto/balloon.c b/src/crypto/balloon.c new file mode 100644 index 0000000..ab0bab2 --- /dev/null +++ b/src/crypto/balloon.c @@ -0,0 +1,74 @@ +// https://github.com/itwysgsl/balloon/ + +#include "balloon.h" +#include "blake256.h" + +#include +#include +#include + +uint64_t u8tou64(uint8_t const* u8){ + uint64_t u64; + memcpy(&u64, u8, sizeof(u64)); + return u64; +} + +void balloon(const unsigned char* input, char* output, int length, const unsigned char* salt, int salt_length) +{ + const uint64_t s_cost = 128; + const uint64_t t_cost = 2; + const int delta = 3; + + hmac_state ctx; + uint8_t blocks[128][64]; + + // Step 1: Expand input into buffer + uint64_t cnt = 0; + blake256_init(&ctx); + blake256_update(&ctx, (uint8_t *)&cnt, sizeof((uint8_t *)&cnt)); + blake256_update(&ctx, input, length); + blake256_update(&ctx, salt, salt_length); + blake256_final(&ctx, blocks[0]); + cnt++; + + for (int m = 1; m < s_cost; m++) { + blake256_update(&ctx, (uint8_t *)&cnt, sizeof((uint8_t *)&cnt)); + blake256_update(&ctx, blocks[m - 1], 64); + blake256_final(&ctx, blocks[m]); + cnt++; + } + + // Step 2: Mix buffer contents + for (uint64_t t = 0; t < t_cost; t++) { + for (uint64_t m = 0; m < s_cost; m++) { + // Step 2a: Hash last and current blocks + blake256_update(&ctx, (uint8_t *)&cnt, sizeof((uint8_t *)&cnt)); + blake256_update(&ctx, blocks[(m - 1) % s_cost], 64); + blake256_update(&ctx, blocks[m], 64); + blake256_final(&ctx, blocks[m]); + cnt++; + + for (uint64_t i = 0; i < delta; i++) { + uint8_t index[64]; + blake256_update(&ctx, (uint8_t *)&t, sizeof((uint8_t *)&t)); + blake256_update(&ctx, (uint8_t *)&cnt, sizeof((uint8_t *)&cnt)); + blake256_update(&ctx, (uint8_t *)&m, sizeof((uint8_t *)&m)); + blake256_update(&ctx, salt, salt_length); + blake256_update(&ctx, (uint8_t *)&i, sizeof((uint8_t *)&i)); + blake256_final(&ctx, index); + cnt++; + + uint64_t other = u8tou64(index) % s_cost; + cnt++; + + blake256_update(&ctx, (uint8_t *)&cnt, sizeof((uint8_t *)&cnt)); + blake256_update(&ctx, blocks[m], 64); + blake256_update(&ctx, blocks[other], 64); + blake256_final(&ctx, blocks[m]); + cnt++; + } + } + } + + memcpy(output, blocks[s_cost - 1], 32); +} diff --git a/src/crypto/balloon.h b/src/crypto/balloon.h new file mode 100644 index 0000000..f826b4d --- /dev/null +++ b/src/crypto/balloon.h @@ -0,0 +1,16 @@ + // https://github.com/itwysgsl/balloon/ + +#ifndef BALLOON_H +#define BALLOON_H + +#ifdef __cplusplus +extern "C" { +#endif + +void balloon(const unsigned char* input, char* output, int length, const unsigned char* salt, int salt_length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/crypto/crypto.cpp b/src/crypto/crypto.cpp index 03375f1..15897f2 100644 --- a/src/crypto/crypto.cpp +++ b/src/crypto/crypto.cpp @@ -50,6 +50,43 @@ namespace Crypto { ge_p3_tobytes(reinterpret_cast(&pub), &point); } + void crypto_ops::generate_keys_from_seed(PublicKey &pub, SecretKey &sec, SecretKey &seed) { + ge_p3 point; + sec = seed; + sc_reduce32(reinterpret_cast(&sec)); + ge_scalarmult_base(&point, reinterpret_cast(&sec)); + ge_p3_tobytes(reinterpret_cast(&pub), &point); + } + + void crypto_ops::generate_deterministic_keys(PublicKey &pub, SecretKey &sec, SecretKey& second) { + lock_guard lock(random_lock); + ge_p3 point; + sec = second; + sc_reduce32(reinterpret_cast(&sec)); // reduce in case second round of keys (sendkeys) + ge_scalarmult_base(&point, reinterpret_cast(&sec)); + ge_p3_tobytes(reinterpret_cast(&pub), &point); + } + + SecretKey crypto_ops::generate_m_keys(PublicKey &pub, SecretKey &sec, const SecretKey& recovery_key, bool recover) { + lock_guard lock(random_lock); + ge_p3 point; + SecretKey rng; + if (recover) + { + rng = recovery_key; + } + else + { + random_scalar(reinterpret_cast(rng)); + } + sec = rng; + sc_reduce32(reinterpret_cast(&sec)); // reduce in case second round of keys (sendkeys) + ge_scalarmult_base(&point, reinterpret_cast(&sec)); + ge_p3_tobytes(reinterpret_cast(&pub), &point); + + return rng; + } + bool crypto_ops::check_key(const PublicKey &key) { ge_p3 point; return ge_frombytes_vartime(&point, reinterpret_cast(&key)) == 0; @@ -335,7 +372,7 @@ namespace Crypto { }; static inline size_t rs_comm_size(size_t pubs_count) { - return sizeof(rs_comm) + pubs_count * sizeof(rs_comm().ab[0]); + return sizeof(rs_comm) + pubs_count * sizeof(((rs_comm*)0)->ab[0]); } void crypto_ops::generate_ring_signature(const Hash &prefix_hash, const KeyImage &image, diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 119f76c..5fdc232 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -40,6 +40,12 @@ struct EllipticCurveScalar { static void generate_keys(PublicKey &, SecretKey &); friend void generate_keys(PublicKey &, SecretKey &); + static void generate_keys_from_seed(PublicKey &, SecretKey &, SecretKey &); + friend void generate_keys_from_seed(PublicKey &, SecretKey &, SecretKey &); + static void generate_deterministic_keys(PublicKey &pub, SecretKey &sec, SecretKey& second); + friend void generate_deterministic_keys(PublicKey &pub, SecretKey &sec, SecretKey& second); + static SecretKey generate_m_keys(PublicKey &pub, SecretKey &sec, const SecretKey& recovery_key = SecretKey(), bool recover = false); + friend SecretKey generate_m_keys(PublicKey &pub, SecretKey &sec, const SecretKey& recovery_key, bool recover); static bool check_key(const PublicKey &); friend bool check_key(const PublicKey &); static bool secret_key_to_public_key(const SecretKey &, PublicKey &); @@ -129,6 +135,19 @@ struct EllipticCurveScalar { crypto_ops::generate_keys(pub, sec); } + inline void generate_keys_from_seed(PublicKey &pub, SecretKey &sec, SecretKey &seed) { + crypto_ops::generate_keys_from_seed(pub, sec, seed); + } + +// + inline SecretKey generate_m_keys(PublicKey &pub, SecretKey &sec, const SecretKey& recovery_key = SecretKey(), bool recover = false) { + return crypto_ops::generate_m_keys(pub, sec, recovery_key, recover); + } +// + inline void generate_deterministic_keys(PublicKey &pub, SecretKey &sec, SecretKey& second) { + crypto_ops::generate_deterministic_keys(pub, sec, second); + } + /* Check a public key. Returns true if it is valid, false otherwise. */ inline bool check_key(const PublicKey &key) { diff --git a/src/crypto/groestl.c b/src/crypto/groestl.c index e194d7e..9be7ae3 100644 --- a/src/crypto/groestl.c +++ b/src/crypto/groestl.c @@ -356,5 +356,5 @@ static int crypto_hash(unsigned char *out, groestl(in, 8*len, out); return 0; } +*/ -*/ \ No newline at end of file diff --git a/src/crypto/groestl.h b/src/crypto/groestl.h index 078515c..ae6eb21 100644 --- a/src/crypto/groestl.h +++ b/src/crypto/groestl.h @@ -1,11 +1,15 @@ #ifndef __hash_h #define __hash_h + +#ifdef __cplusplus +extern "C" { +#endif + /* #include "crypto_uint8.h" #include "crypto_uint32.h" #include "crypto_uint64.h" #include "crypto_hash.h" - typedef crypto_uint8 uint8_t; typedef crypto_uint32 uint32_t; typedef crypto_uint64 uint64_t; @@ -45,9 +49,10 @@ typedef struct { data buffer */ } hashState; -/*void Init(hashState*); -void Update(hashState*, const BitSequence*, DataLength); -void Final(hashState*, BitSequence*); */ +static void Init(hashState*); +static void Update(hashState*, const BitSequence*, DataLength); +static void Final(hashState*, BitSequence*); + void groestl(const BitSequence*, DataLength, BitSequence*); /* NIST API end */ @@ -57,4 +62,8 @@ int crypto_hash(unsigned char *out, unsigned long long len); */ +#ifdef __cplusplus +} +#endif + #endif /* __hash_h */ diff --git a/src/crypto/hash-ops.h b/src/crypto/hash-ops.h index df3a89c..432a138 100644 --- a/src/crypto/hash-ops.h +++ b/src/crypto/hash-ops.h @@ -53,7 +53,7 @@ enum { void cn_fast_hash(const void *data, size_t length, char *hash); -void cn_slow_hash_f(void *, const void *, size_t, void *); +void cn_slow_hash_f(void *, const void *, size_t, void *, int); void hash_extra_blake(const void *data, size_t length, char *hash); void hash_extra_groestl(const void *data, size_t length, char *hash); diff --git a/src/crypto/hash.h b/src/crypto/hash.h index d8a6a65..8ba31b7 100644 --- a/src/crypto/hash.h +++ b/src/crypto/hash.h @@ -9,6 +9,7 @@ #include #include "generic-ops.h" +#include "balloon.h" namespace Crypto { @@ -43,13 +44,18 @@ namespace Crypto { private: void *data; - friend inline void cn_slow_hash(cn_context &, const void *, size_t, Hash &); + friend inline void cn_slow_hash(cn_context &, const void *, size_t, Hash &, int); }; - inline void cn_slow_hash(cn_context &context, const void *data, size_t length, Hash &hash) { - (*cn_slow_hash_f)(context.data, data, length, reinterpret_cast(&hash)); + inline void cn_slow_hash(cn_context &context, const void *data, size_t length, Hash &hash, int variant = 0) { + (*cn_slow_hash_f)(context.data, data, length, reinterpret_cast(&hash), variant); } + inline void balloon_hash(const unsigned char* input, Hash &output, int length, const unsigned char* salt, int salt_length) { + balloon(input, reinterpret_cast(&output), length, salt, salt_length); + } + + inline void tree_hash(const Hash *hashes, size_t count, Hash &root_hash) { tree_hash(reinterpret_cast(hashes), count, reinterpret_cast(&root_hash)); } @@ -62,6 +68,8 @@ namespace Crypto { tree_hash_from_branch(reinterpret_cast(branch), depth, reinterpret_cast(&leaf), path, reinterpret_cast(&root_hash)); } + + } CRYPTO_MAKE_HASHABLE(Hash) diff --git a/src/crypto/keccak.c b/src/crypto/keccak.c index 3ee2a88..48fd7a1 100644 --- a/src/crypto/keccak.c +++ b/src/crypto/keccak.c @@ -79,6 +79,13 @@ int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen) uint8_t temp[144]; int i, rsiz, rsizw; + /* for some reason the enum from hash-ops.h is not valid here when + compiling - is this a C vs C++ thing? Anyhow, lets just redefine it for + now. */ + + const int HASH_DATA_AREA = 136; + + rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; rsizw = rsiz / 8; diff --git a/src/crypto/slow-hash.c b/src/crypto/slow-hash.c index 7d09004..d694c15 100644 --- a/src/crypto/slow-hash.c +++ b/src/crypto/slow-hash.c @@ -22,10 +22,10 @@ #include "hash-ops.h" #include "oaes_lib.h" -void (*cn_slow_hash_fp)(void *, const void *, size_t, void *); +void(*cn_slow_hash_fp)(void *, const void *, size_t, void *, int); -void cn_slow_hash_f(void * a, const void * b, size_t c, void * d){ -(*cn_slow_hash_fp)(a, b, c, d); +void cn_slow_hash_f(void * a, const void * b, size_t c, void * d, int v){ + (*cn_slow_hash_fp)(a, b, c, d, v); } #if defined(__GNUC__) diff --git a/src/crypto/slow-hash.inl b/src/crypto/slow-hash.inl index f29d17a..118d4a3 100644 --- a/src/crypto/slow-hash.inl +++ b/src/crypto/slow-hash.inl @@ -3,13 +3,53 @@ // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include +#if defined(WIN32) +#include +#else +#include +#endif + +#define xor64(a, b) *((uint64_t*)a) ^= b + +#define VARIANT1_1(p) \ + do if (variant > 0) \ + { \ + const uint8_t tmp = ((const uint8_t*)(p))[11]; \ + static const uint32_t table = 0x75310; \ + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ + ((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \ + } while(0) + +#define VARIANT1_2(p) \ + do if (variant > 0) \ + { \ + xor64(p, tweak1_2); \ + } while(0) + +#define VARIANT1_CHECK() \ + do if (length < 43) \ + { \ + printf("Cryptonight variants need at least 43 bytes of data"); \ + exit(1); \ + } while(0) + +#define NONCE_POINTER (((const uint8_t*)data)+35) + +#define VARIANT1_INIT64() \ + if (variant > 0) \ + { \ + VARIANT1_CHECK(); \ + } \ + const uint64_t tweak1_2 = variant > 0 ? (ctx->state.hs.w[24] ^ (*((const uint64_t*)NONCE_POINTER))) : 0 + static void #if defined(AESNI) cn_slow_hash_aesni #else cn_slow_hash_noaesni #endif -(void *restrict context, const void *restrict data, size_t length, void *restrict hash) +(void *restrict context, const void *restrict data, size_t length, void *restrict hash, int variant) { #define ctx ((struct cn_ctx *) context) ALIGNED_DECL(uint8_t ExpandedKey[256], 16); @@ -19,6 +59,9 @@ cn_slow_hash_noaesni hash_process(&ctx->state.hs, (const uint8_t*) data, length); memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); + + VARIANT1_INIT64(); + #if defined(AESNI) memcpy(ExpandedKey, ctx->state.hs.b, AES_KEY_SIZE); ExpandAESKey256(ExpandedKey); @@ -99,6 +142,8 @@ cn_slow_hash_noaesni b_x = _mm_xor_si128(b_x, c_x); _mm_store_si128((__m128i *)&ctx->long_state[a[0] & 0x1FFFF0], b_x); + VARIANT1_1(&ctx->long_state[a[0] & 0x1FFFF0]); + nextblock = (uint64_t *)&ctx->long_state[c[0] & 0x1FFFF0]; b[0] = nextblock[0]; b[1] = nextblock[1]; @@ -127,6 +172,9 @@ cn_slow_hash_noaesni a[0] ^= b[0]; a[1] ^= b[1]; + + VARIANT1_2(dst + 1); + b_x = c_x; //__builtin_prefetch(&ctx->long_state[a[0] & 0x1FFFF0], 0, 3); } diff --git a/src/version.h.in b/src/version.h.in index 802686f..9c53b57 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,4 +1,4 @@ #define BUILD_COMMIT_ID "@VERSION@" -#define PROJECT_VERSION "0.1.1" -#define PROJECT_VERSION_BUILD_NO "cedi0010" +#define PROJECT_VERSION "0.1.4" +#define PROJECT_VERSION_BUILD_NO "ctl0013" #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")" diff --git a/tests/CoreTests/BlockValidation.cpp b/tests/CoreTests/BlockValidation.cpp index dcaa79b..4bc5094 100644 --- a/tests/CoreTests/BlockValidation.cpp +++ b/tests/CoreTests/BlockValidation.cpp @@ -26,7 +26,7 @@ namespace { CryptoNote::Block blk_prev = blk_last; for (size_t i = 0; i < new_block_count; ++i) { CryptoNote::Block blk_next; - CryptoNote::difficulty_type diffic = currency.nextDifficulty(timestamps, cummulative_difficulties); + CryptoNote::difficulty_type diffic = currency.nextDifficulty(block_major_version, timestamps, cummulative_difficulties); if (!generator.constructBlockManually(blk_next, blk_prev, miner_account, test_generator::bf_major_ver | test_generator::bf_timestamp | test_generator::bf_diffic, block_major_version, 0, blk_prev.timestamp, Crypto::Hash(), diffic)) { @@ -190,7 +190,7 @@ bool gen_block_invalid_nonce::generate(std::vector& events) co } // Create invalid nonce - difficulty_type diffic = m_currency.nextDifficulty(timestamps, commulative_difficulties); + difficulty_type diffic = m_currency.nextDifficulty(m_blockMajorVersion, timestamps, commulative_difficulties); assert(1 < diffic); const Block& blk_last = boost::get(events.back()); uint64_t timestamp = blk_last.timestamp; @@ -583,7 +583,7 @@ gen_block_invalid_binary_format::gen_block_invalid_binary_format(uint8_t blockMa m_corrupt_blocks_begin_idx(0), m_blockMajorVersion(blockMajorVersion) { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); - currencyBuilder.upgradeHeight(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : 0); + currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : 0); m_currency = currencyBuilder.currency(); REGISTER_CALLBACK("check_all_blocks_purged", gen_block_invalid_binary_format::check_all_blocks_purged); @@ -616,7 +616,7 @@ bool gen_block_invalid_binary_format::generate(std::vector& ev do { blk_last = boost::get(events.back()); - diffic = m_currency.nextDifficulty(timestamps, cummulative_difficulties); + diffic = m_currency.nextDifficulty(m_blockMajorVersion, timestamps, cummulative_difficulties); if (!lift_up_difficulty(m_currency, events, timestamps, cummulative_difficulties, generator, 1, blk_last, miner_account, m_blockMajorVersion)) { return false; @@ -633,7 +633,7 @@ bool gen_block_invalid_binary_format::generate(std::vector& ev std::vector tx_hashes; tx_hashes.push_back(getObjectHash(tx_0)); size_t txs_size = getObjectBinarySize(tx_0); - diffic = m_currency.nextDifficulty(timestamps, cummulative_difficulties); + diffic = m_currency.nextDifficulty(m_blockMajorVersion, timestamps, cummulative_difficulties); if (!generator.constructBlockManually(blk_test, blk_last, miner_account, test_generator::bf_major_ver | test_generator::bf_diffic | test_generator::bf_timestamp | test_generator::bf_tx_hashes, m_blockMajorVersion, 0, blk_last.timestamp, Crypto::Hash(), diffic, Transaction(), tx_hashes, txs_size)) diff --git a/tests/CoreTests/BlockValidation.h b/tests/CoreTests/BlockValidation.h index 7618b37..7994b63 100644 --- a/tests/CoreTests/BlockValidation.h +++ b/tests/CoreTests/BlockValidation.h @@ -17,7 +17,7 @@ class CheckBlockPurged : public test_chain_unit_base { assert(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 || blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_2); CryptoNote::CurrencyBuilder currencyBuilder(m_logger); - currencyBuilder.upgradeHeight(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0)); + currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0)); m_currency = currencyBuilder.currency(); REGISTER_CALLBACK("check_block_purged", CheckBlockPurged::check_block_purged); @@ -60,7 +60,7 @@ struct CheckBlockAccepted : public test_chain_unit_base { assert(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 || blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_2); CryptoNote::CurrencyBuilder currencyBuilder(m_logger); - currencyBuilder.upgradeHeight(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0)); + currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0)); m_currency = currencyBuilder.currency(); REGISTER_CALLBACK("check_block_accepted", CheckBlockAccepted::check_block_accepted); @@ -287,7 +287,7 @@ struct gen_block_is_too_big : public CheckBlockPurged gen_block_is_too_big(uint8_t blockMajorVersion) : CheckBlockPurged(1, blockMajorVersion) { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); - currencyBuilder.upgradeHeight(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0)); + currencyBuilder.upgradeHeightV2(blockMajorVersion == CryptoNote::BLOCK_MAJOR_VERSION_1 ? UNDEF_HEIGHT : UINT64_C(0)); currencyBuilder.maxBlockSizeInitial(std::numeric_limits::max() / 2); m_currency = currencyBuilder.currency(); } diff --git a/tests/CoreTests/Deposit.h b/tests/CoreTests/Deposit.h index cf5c81d..0feae81 100644 --- a/tests/CoreTests/Deposit.h +++ b/tests/CoreTests/Deposit.h @@ -14,7 +14,7 @@ namespace DepositTests { struct DepositTestsBase : public test_chain_unit_base { DepositTestsBase() { - m_currency = CryptoNote::CurrencyBuilder(m_logger).upgradeHeight(0).depositMinTerm(10).depositMinTotalRateFactor(100).currency(); + m_currency = CryptoNote::CurrencyBuilder(m_logger).upgradeHeightV2(0).depositMinTerm(10).depositMinTotalRateFactor(100).currency(); from.generate(); to.generate(); REGISTER_CALLBACK_METHOD(DepositTestsBase, mark_invalid_block); @@ -64,7 +64,7 @@ struct DepositIndexTest : public DepositTestsBase { using Core = CryptoNote::core; using Events = std::vector; DepositIndexTest() { - m_currency = CryptoNote::CurrencyBuilder(m_logger).upgradeHeight(0).depositMinTerm(10).depositMinTotalRateFactor(100).mininumFee(1000).currency(); + m_currency = CryptoNote::CurrencyBuilder(m_logger).upgradeHeightV2(0).depositMinTerm(10).depositMinTotalRateFactor(100).mininumFee(1000).currency(); REGISTER_CALLBACK_METHOD(DepositIndexTest, interestZero); REGISTER_CALLBACK_METHOD(DepositIndexTest, interestOneMinimal); REGISTER_CALLBACK_METHOD(DepositIndexTest, interestTwoMininmal); @@ -100,7 +100,7 @@ struct DepositIndexTest : public DepositTestsBase { struct EmissionTest : public DepositTestsBase { EmissionTest() { - m_currency = CryptoNote::CurrencyBuilder(m_logger).upgradeHeight(0).depositMinTerm(10).depositMinTotalRateFactor(100).currency(); + m_currency = CryptoNote::CurrencyBuilder(m_logger).upgradeHeightV2(0).depositMinTerm(10).depositMinTotalRateFactor(100).currency(); REGISTER_CALLBACK_METHOD(EmissionTest, save_emission_before); REGISTER_CALLBACK_METHOD(EmissionTest, save_emission_after); } diff --git a/tests/CoreTests/DoubleSpend.cpp b/tests/CoreTests/DoubleSpend.cpp index bb3a92f..95cb200 100644 --- a/tests/CoreTests/DoubleSpend.cpp +++ b/tests/CoreTests/DoubleSpend.cpp @@ -79,7 +79,7 @@ DoubleSpendBase::DoubleSpendBase() : send_amount(MK_COINS(17)), has_invalid_tx(false) { - m_currency = CurrencyBuilder(m_logger).upgradeHeight(0).currency(); + m_currency = CurrencyBuilder(m_logger).upgradeHeightV2(0).currency(); m_outputTxKey = generateKeyPair(); m_bob_account.generate(); m_alice_account.generate(); diff --git a/tests/CoreTests/TransactionValidation.cpp b/tests/CoreTests/TransactionValidation.cpp index 8bd5d0d..056e6e5 100644 --- a/tests/CoreTests/TransactionValidation.cpp +++ b/tests/CoreTests/TransactionValidation.cpp @@ -701,7 +701,7 @@ bool GenerateTransactionWithZeroFee::generate(std::vector& eve MultiSigTx_OutputSignatures::MultiSigTx_OutputSignatures(size_t givenKeys, uint32_t requiredSignatures, bool shouldSucceed) : m_givenKeys(givenKeys), m_requiredSignatures(requiredSignatures), m_shouldSucceed(shouldSucceed) { - m_currency = CurrencyBuilder(m_logger).upgradeHeight(0).currency(); + m_currency = CurrencyBuilder(m_logger).upgradeHeightV2(0).currency(); for (size_t i = 0; i < m_givenKeys; ++i) { AccountBase acc; @@ -832,7 +832,7 @@ MultiSigTx_Input::MultiSigTx_Input( m_givenSignatures(givenSignatures), m_inputShouldSucceed(inputShouldSucceed) { - m_currency = CurrencyBuilder(m_logger).upgradeHeight(0).currency(); + m_currency = CurrencyBuilder(m_logger).upgradeHeightV2(0).currency(); } bool MultiSigTx_Input::generate(std::vector& events) const { diff --git a/tests/CoreTests/Upgrade.cpp b/tests/CoreTests/Upgrade.cpp index e575bc9..0d542d4 100644 --- a/tests/CoreTests/Upgrade.cpp +++ b/tests/CoreTests/Upgrade.cpp @@ -34,7 +34,8 @@ namespace { gen_upgrade::gen_upgrade() : m_invalidBlockIndex(0), m_checkBlockTemplateVersionCallCounter(0) { CryptoNote::CurrencyBuilder currencyBuilder(m_logger); currencyBuilder.maxBlockSizeInitial(std::numeric_limits::max() / 2); - currencyBuilder.upgradeHeight(UpgradeDetectorBase::UNDEF_HEIGHT); + currencyBuilder.upgradeHeightV2(UpgradeDetectorBase::UNDEF_HEIGHT); + currencyBuilder.upgradeHeightV3(UpgradeDetectorBase::UNDEF_HEIGHT); m_currency = currencyBuilder.currency(); REGISTER_CALLBACK_METHOD(gen_upgrade, markInvalidBlock); @@ -191,8 +192,8 @@ bool gen_upgrade::checkBlockTemplateVersion(CryptoNote::core& c, uint8_t expecte difficulty_type diff; uint32_t height; CHECK_TEST_CONDITION(c.get_block_template(b, account.getAccountKeys().address, diff, height, BinaryArray())); - CHECK_EQ(b.majorVersion, expectedMajorVersion); - CHECK_EQ(b.minorVersion, expectedMinorVersion); + CHECK_EQ(static_cast(b.majorVersion), static_cast(expectedMajorVersion)); + CHECK_EQ(static_cast(b.minorVersion), static_cast(expectedMinorVersion)); return true; } diff --git a/tests/Difficulty/Difficulty.cpp b/tests/Difficulty/Difficulty.cpp index a54efe1..982a8bc 100644 --- a/tests/Difficulty/Difficulty.cpp +++ b/tests/Difficulty/Difficulty.cpp @@ -45,6 +45,7 @@ int main(int argc, char *argv[]) { begin = end - currency.difficultyWindow(); } uint64_t res = currency.nextDifficulty( + CryptoNote::BLOCK_MAJOR_VERSION_1, vector(timestamps.begin() + begin, timestamps.begin() + end), vector(cumulative_difficulties.begin() + begin, cumulative_difficulties.begin() + end)); if (res != difficulty) { diff --git a/tests/UnitTests/TestUpgradeDetector.cpp b/tests/UnitTests/TestUpgradeDetector.cpp index 43c5ed9..e66a238 100644 --- a/tests/UnitTests/TestUpgradeDetector.cpp +++ b/tests/UnitTests/TestUpgradeDetector.cpp @@ -33,7 +33,8 @@ namespace { currencyBuilder.upgradeVotingThreshold(90); currencyBuilder.upgradeVotingWindow(720); currencyBuilder.upgradeWindow(720); - currencyBuilder.upgradeHeight(upgradeHeight); + currencyBuilder.upgradeHeightV2(upgradeHeight); + currencyBuilder.upgradeHeightV3(UpgradeDetector::UNDEF_HEIGHT); return currencyBuilder.currency(); } @@ -153,14 +154,14 @@ namespace { // Upgrade to v2 is here createBlocks(blocks, 1, BLOCK_MAJOR_VERSION_2, BLOCK_MINOR_VERSION_0); - createBlocks(blocks, currency.upgradeVotingWindow(), BLOCK_MAJOR_VERSION_2, BLOCK_MINOR_VERSION_1); + createBlocks(blocks, currency.upgradeVotingWindow() * currency.upgradeVotingThreshold() / 100, BLOCK_MAJOR_VERSION_2, BLOCK_MINOR_VERSION_1); uint64_t votingCompleteHeigntV3 = blocks.size() - 1; uint64_t upgradeHeightV3 = currency.calculateUpgradeHeight(votingCompleteHeigntV3); createBlocks(blocks, upgradeHeightV3 - blocks.size(), BLOCK_MAJOR_VERSION_2, BLOCK_MINOR_VERSION_0); // Upgrade to v3 is here createBlocks(blocks, 1, BLOCK_V3, BLOCK_MINOR_VERSION_0); - createBlocks(blocks, currency.upgradeVotingWindow(), BLOCK_V3, BLOCK_MINOR_VERSION_1); + createBlocks(blocks, currency.upgradeVotingWindow() * currency.upgradeVotingThreshold() / 100, BLOCK_V3, BLOCK_MINOR_VERSION_1); uint64_t votingCompleteHeigntV4 = blocks.size() - 1; uint64_t upgradeHeightV4 = currency.calculateUpgradeHeight(votingCompleteHeigntV4); createBlocks(blocks, upgradeHeightV4 - blocks.size(), BLOCK_V3, BLOCK_MINOR_VERSION_0);