├── .bazelrc ├── .clang-format ├── .github ├── issue_template.md ├── pull_request_template.md └── workflows │ └── test.yml ├── .gitignore ├── BUILD ├── CHANGELOG ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── WORKSPACE ├── common ├── BUILD ├── commands │ ├── BUILD │ ├── command.h │ ├── errors.cc │ └── errors.h ├── common.cc ├── common.h ├── converter.cc ├── converter.h ├── crypto │ ├── BUILD │ ├── argon2_provider.cc │ ├── argon2_provider.h │ ├── manager.cc │ ├── manager.h │ ├── provider_base.cc │ ├── provider_base.h │ ├── tests │ │ └── types.cc │ ├── types.cc │ └── types.h ├── flags.cc ├── flags.h ├── grpc_server_base.cc ├── grpc_server_base.h ├── http_server_base.cc ├── http_server_base.h ├── server_base.h ├── stats │ ├── BUILD │ ├── session.cc │ └── session.h └── tests │ ├── BUILD │ └── runner.cc ├── docker └── BUILD ├── docs ├── checksum_validation.md ├── getting_started.md ├── hip │ ├── 001-sign_bundle.md │ ├── 002-signing_server.md │ └── template.md ├── http_rest_api.md ├── integration_scenarios.md ├── pull_request_template.md ├── python │ ├── .gitignore │ ├── README.md │ ├── argon2_authentication_token.py │ ├── generate_proto.sh │ └── ssl_client.py ├── secure_server.md └── ssl │ ├── .gitignore │ ├── grpc │ ├── 01_generate_ca.sh │ ├── 02_generate_server.sh │ └── 03_generate_client.sh │ └── rest │ └── generate.sh ├── doxyfile ├── hooks ├── autohook.sh ├── pre-commit │ ├── 01-buildifier-check │ ├── 02-cpplint │ └── 03-format-check └── scripts │ ├── buildifier_check │ ├── cpplint │ └── format_check ├── hub.png ├── hub ├── BUILD ├── auth │ ├── BUILD │ ├── dummy_provider.h │ ├── hmac_provider.cc │ ├── hmac_provider.h │ ├── manager.cc │ ├── manager.h │ ├── provider.h │ ├── sign_bundle_context.cc │ ├── sign_bundle_context.h │ └── tests │ │ └── hmac_provider.cc ├── bundle │ ├── BUILD │ ├── bundle_utils.cc │ └── bundle_utils.h ├── commands │ ├── BUILD │ ├── balance_subscription.cc │ ├── balance_subscription.h │ ├── converter.cc │ ├── converter.h │ ├── create_user.cc │ ├── create_user.h │ ├── events.h │ ├── factory.h │ ├── get_address_info.cc │ ├── get_address_info.h │ ├── get_balance.cc │ ├── get_balance.h │ ├── get_deposit_address.cc │ ├── get_deposit_address.h │ ├── get_seed_for_address.cc │ ├── get_seed_for_address.h │ ├── get_seed_for_uuid.cc │ ├── get_seed_for_uuid.h │ ├── get_stats.cc │ ├── get_stats.h │ ├── get_user_history.cc │ ├── get_user_history.h │ ├── helper.cc │ ├── helper.h │ ├── process_transfer_batch.cc │ ├── process_transfer_batch.h │ ├── recover_funds.cc │ ├── recover_funds.h │ ├── sign_bundle.cc │ ├── sign_bundle.h │ ├── sweep_detail.cc │ ├── sweep_detail.h │ ├── sweep_info.cc │ ├── sweep_info.h │ ├── sweep_subscription.cc │ ├── sweep_subscription.h │ ├── tests │ │ ├── helper.cc │ │ ├── helper.h │ │ ├── runner.h │ │ ├── test_balance_subscription.cc │ │ ├── test_create_user.cc │ │ ├── test_get_address_info.cc │ │ ├── test_get_balance.cc │ │ ├── test_get_deposit_address.cc │ │ ├── test_get_user_history.cc │ │ ├── test_process_transfer_batch.cc │ │ ├── test_user_withdraw.cc │ │ └── test_user_withdraw_cancel.cc │ ├── user_withdraw.cc │ ├── user_withdraw.h │ ├── user_withdraw_cancel.cc │ ├── user_withdraw_cancel.h │ ├── was_address_spent_from.cc │ ├── was_address_spent_from.h │ ├── was_withdrawal_cancelled.cc │ └── was_withdrawal_cancelled.h ├── crypto │ ├── BUILD │ ├── local_provider.cc │ ├── local_provider.h │ ├── remote_signing_provider.cc │ ├── remote_signing_provider.h │ └── tests │ │ └── local_signing_provider.cc ├── db │ ├── BUILD │ ├── CPPLINT.cfg │ ├── connection.h │ ├── connection_impl.h │ ├── db.cc │ ├── db.h │ ├── helper.cc │ ├── helper.h │ ├── mariadb.cc │ ├── mariadb.h │ ├── sqlite3.cc │ ├── sqlite3.h │ ├── tests │ │ └── trigger.cc │ └── types.h ├── iota │ ├── BUILD │ ├── local_pow.cc │ ├── local_pow.h │ ├── pow.cc │ ├── pow.h │ ├── remote_pow.h │ └── tests │ │ └── local_pow.cc ├── main.cc ├── server │ ├── BUILD │ ├── grpc.cc │ ├── grpc.h │ ├── grpc_server.cc │ ├── grpc_server.h │ ├── http_json_server.cc │ ├── http_json_server.h │ ├── hub_server_base.cc │ └── hub_server_base.h ├── service │ ├── BUILD │ ├── CPPLINT.cfg │ ├── address_monitor.cc │ ├── address_monitor.h │ ├── attachment_service.cc │ ├── attachment_service.h │ ├── scheduled_service.cc │ ├── scheduled_service.h │ ├── service.cc │ ├── service.h │ ├── sweep_service.cc │ ├── sweep_service.h │ ├── tests │ │ ├── address_monitor.cc │ │ └── scheduled_service.cc │ ├── user_address_monitor.cc │ └── user_address_monitor.h └── tests │ ├── BUILD │ ├── runner.cc │ └── runner.h ├── proto ├── BUILD ├── hub.proto ├── messages.proto ├── signing_server.proto └── signing_server_messages.proto ├── requirements.txt ├── schema ├── BUILD ├── ddl2cpp.py ├── delta.mariadb.sql ├── delta.sqlite3.sql ├── schema.sql ├── triggers.mariadb.sql └── triggers.sqlite3.sql ├── signing_server ├── BUILD ├── commands │ ├── BUILD │ ├── get_address_for_uuid.cc │ ├── get_address_for_uuid.h │ ├── get_security_level.cc │ ├── get_security_level.h │ ├── get_seed_for_uuid.cc │ ├── get_seed_for_uuid.h │ ├── get_signature_for_uuid.cc │ ├── get_signature_for_uuid.h │ ├── helper.cc │ └── helper.h ├── grpc.cc ├── grpc.h ├── main.cc ├── server.cc └── server.h ├── third-party ├── cpprest │ └── BUILD.bzl ├── date │ └── BUILD.bzl ├── mariadb_connector │ └── BUILD.bzl ├── sqlpp11 │ └── BUILD.bzl ├── sqlpp11mysql │ └── BUILD.bzl └── sqlpp11sqlite │ └── BUILD.bzl └── tools ├── bazel.rc ├── buildifier ├── ci └── build.sh ├── cpplint ├── cpplint.py └── remote.rc /.bazelrc: -------------------------------------------------------------------------------- 1 | import %workspace%/tools/bazel.rc 2 | import %workspace%/tools/remote.rc 3 | try-import %workspace%/user.bazelrc 4 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | The issue tracker is only for reporting bugs or submitting feature requests. 4 | If you have general questions on IOTA you can go to https://iota.stackexchange.com/, https://helloiota.com/, or browse Discord channels (https://discord.gg/C88Wexg). 5 | 6 | 7 | 8 | ### Bug description 9 | A general description of the bug. 10 | 11 | ### Hardware Spec 12 | On what hardware is the node running on? 13 | 14 | ### Steps To Reproduce 15 | 1. 16 | 2. 17 | 3. 18 | 19 | ### Expected behaviour 20 | What should happen. 21 | 22 | ### Actual behaviour 23 | What really happened. 24 | 25 | ### Errors 26 | Paste any errors that you see. 27 | 28 | 29 | 30 | 31 | *Note* 32 | The feature request will probably be integrated faster if you do a pull request for it. 33 | If you want to discuss the feature before you actually write the code you are welcome to do it by first submitting an issue. 34 | 35 | ### Description 36 | Briefly describe the feature you want. 37 | 38 | ### Motivation 39 | Explain why this feature is needed. 40 | 41 | ### Requirements 42 | Create a list of what you want this feature request to fulfill. 43 | 44 | ### Open Questions (optional) 45 | Anything you want to discuss. 46 | 47 | ### Am I planning to do it myself with a PR? 48 | Yes/No. 49 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 9 | 10 | # Description 11 | 12 | _Please include a summary of the change. Include the motivation for the change._ 13 | 14 | Fixes # (issue) 15 | 16 | ## Type of change 17 | 18 | _Please delete options that are not relevant._ 19 | 20 | - Bug fix (a non-breaking change which fixes an issue) 21 | - Enhancement (a non-breaking change which adds functionality) 22 | - Breaking change (fix or feature that would cause existing functionality to not work as expected) 23 | - Documentation Fix 24 | 25 | # How Has This Been Tested? 26 | 27 | _Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration_ 28 | 29 | - Test A 30 | - Test B 31 | 32 | 33 | # Checklist: 34 | 35 | _Please delete items that are not relevant._ 36 | 37 | - [ ] My code follows the style guidelines for this project 38 | - [ ] I have performed a self-review of my own code 39 | - [ ] I have commented my code, particularly in hard-to-understand areas 40 | - [ ] I have made corresponding changes to the documentation 41 | - [ ] I have added tests that prove my fix is effective or that my feature works 42 | - [ ] New and existing unit tests pass locally with my changes 43 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-20.04 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Bazel test opt 17 | run: bazel test -c opt --test_output=all //... 18 | env: 19 | USE_BAZEL_VERSION: 3.3.1 20 | 21 | - name: Bazel test debug 22 | run: bazel test -c dbg --test_output=all //... 23 | env: 24 | USE_BAZEL_VERSION: 3.3.1 25 | 26 | # - name: Bazel test bootlin x86_64 toolchains 27 | # run: bazel test --crosstool_top=@iota_toolchains//tools/x86-64-core-i7--glibc--bleeding-edge-2018.07-1:toolchain --cpu=x86_64 --host_crosstool_top=@bazel_tools//tools/cpp:toolchain //... 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bazel-* 2 | compile_commands.json 3 | GPATH 4 | GTAGS 5 | GRTAGS 6 | .#* 7 | hub.db 8 | .gdb_history 9 | .idea/ 10 | tulsi* 11 | html 12 | -------------------------------------------------------------------------------- /BUILD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/hub/9df503d4def3021b082ba7aaaace7a9265e2ba18/BUILD -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | - Jun 13 2018, PR #154 - hub/crypto: change default argon2 method & parameters 2 | Default argon2 method was changed from argon2i to argon2id 3 | Default argon2 time cost was changed from 1 to 4 4 | Default argon2 memory cost was changed from 1<<16 to 1<<17 5 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @th0br0 @tsvisabo 2 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 |

Responsible disclosure policy

2 | 3 | At the IOTA Foundation, we consider the security of our systems a top priority. But no matter how much effort we put into system security, there can still be vulnerabilities present. If you've discovered a vulnerability, please follow the guidelines below to report it to our security team: 4 | 7 | Please follow these rules when testing/reporting vulnerabilities: 8 | 15 | What we promise: 16 | 22 | We sincerely appreciate the efforts of security researchers in keeping our community safe. 23 | 24 | -------------------------------------------------------------------------------- /common/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "common", 3 | srcs = glob(["*.cc"]), 4 | hdrs = glob([ 5 | "*.h", 6 | ]), 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//common/commands", 10 | "//common/crypto:types", 11 | "//common/stats", 12 | "//proto:hub_grpc_cc", 13 | "@boost//:beast", 14 | "@boost//:property_tree", 15 | "@com_github_gflags_gflags//:gflags", 16 | "@com_github_google_glog//:glog", 17 | "@com_github_grpc_grpc//:grpc++", 18 | ], 19 | ) 20 | -------------------------------------------------------------------------------- /common/commands/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "commands", 3 | srcs = glob(["*.cc"]), 4 | hdrs = glob([ 5 | "*.h", 6 | ]), 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//common/crypto:types", 10 | "//common/stats", 11 | "@boost//:beast", 12 | "@boost//:property_tree", 13 | "@com_github_gflags_gflags//:gflags", 14 | "@com_github_google_glog//:glog", 15 | "@com_github_grpc_grpc//:grpc++", 16 | "@TangleScope//cppclient:beast", 17 | ], 18 | ) 19 | -------------------------------------------------------------------------------- /common/commands/errors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_ERRORS_H_ 9 | #define COMMON_ERRORS_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include "grpc++/grpc++.h" 16 | 17 | namespace common { 18 | 19 | namespace cmd { 20 | 21 | typedef enum { 22 | 23 | OK = 0, 24 | MISSING_ARGUMENT, 25 | WRONG_ARGUMENT_NAME, 26 | CANCELLED, 27 | USER_EXISTS, 28 | USER_DOES_NOT_EXIST, 29 | UNKNOWN_ADDRESS, 30 | UNKNOWN_ERROR, 31 | GET_ADDRESS_FAILED, 32 | INVALID_UUID, 33 | INVALID_CHECKSUM, 34 | INVALID_ADDRESS, 35 | ADDRESS_WAS_SPENT, 36 | IOTA_NODE_UNAVAILABLE, 37 | WITHDRAWAL_CAN_NOT_BE_CANCELLED, 38 | INVALID_AUTHENTICATION, 39 | SIGNATURE_FAILED, 40 | WRONG_USER_ADDRESS, 41 | ADDRESS_NOT_KNOWN_TO_NODE, 42 | ADDRESS_BALANCE_ZERO, 43 | BATCH_INVALID, 44 | BATCH_INCONSISTENT, 45 | BATCH_AMOUNT_NOT_ZERO, 46 | INSUFFICIENT_BALANCE, 47 | 48 | } Error; 49 | 50 | std::unordered_map errorToStringMapCreate(); 51 | 52 | grpc::Status errorToGrpcError(Error err); 53 | 54 | std::string getErrorString(Error); 55 | 56 | } // namespace cmd 57 | } // namespace common 58 | 59 | #endif // COMMON_ERRORS_H_ 60 | -------------------------------------------------------------------------------- /common/common.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "common.h" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace common { 17 | 18 | std::string readFile(const std::string& fileName) { 19 | std::ifstream ifs(fileName.c_str()); 20 | 21 | if (!ifs.good()) { 22 | LOG(FATAL) << "File: " << fileName << " does not exist."; 23 | } 24 | 25 | std::stringstream buffer; 26 | 27 | buffer << ifs.rdbuf(); 28 | return buffer.str(); 29 | } 30 | } // namespace common 31 | -------------------------------------------------------------------------------- /common/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_COMMON_H_ 9 | #define COMMON_COMMON_H_ 10 | 11 | #include 12 | 13 | namespace common { 14 | 15 | std::string readFile(const std::string& fileName); 16 | } 17 | 18 | #endif // COMMON_COMMON_H_ 19 | -------------------------------------------------------------------------------- /common/converter.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "common/converter.h" 9 | 10 | namespace common { 11 | 12 | std::string boolToString(bool isTrue) { return isTrue ? "true" : "false"; } 13 | bool stringToBool(std::string_view isTrueStr) { 14 | return (isTrueStr.compare("true") == 0) ? true : false; 15 | } 16 | 17 | uint64_t timepointToUint64(std::chrono::system_clock::time_point timepoint) { 18 | return std::chrono::duration_cast( 19 | timepoint.time_since_epoch()) 20 | .count(); 21 | } 22 | } // namespace common 23 | -------------------------------------------------------------------------------- /common/converter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_CONVERTER_H_ 9 | #define COMMON_CONVERTER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace common { 16 | std::string boolToString(bool isTrue); 17 | bool stringToBool(std::string_view isTrueStr); 18 | 19 | uint64_t timepointToUint64(std::chrono::system_clock::time_point timepoint); 20 | } 21 | 22 | #endif // COMMON_COMMON_H_ 23 | -------------------------------------------------------------------------------- /common/crypto/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "crypto", 3 | srcs = [ 4 | "manager.cc", 5 | "provider_base.cc", 6 | ], 7 | hdrs = [ 8 | "manager.h", 9 | "provider_base.h", 10 | ], 11 | visibility = ["//visibility:public"], 12 | deps = [ 13 | ":types", 14 | "//proto:signing_server_grpc_cc", 15 | "@optional_lite", 16 | "@org_iota_common//common/helpers:checksum", 17 | ], 18 | ) 19 | 20 | cc_library( 21 | name = "types", 22 | srcs = ["types.cc"], 23 | hdrs = [ 24 | "types.h", 25 | ], 26 | visibility = ["//visibility:public"], 27 | deps = [ 28 | "@boost//:random", 29 | "@com_github_google_glog//:glog", 30 | ], 31 | ) 32 | 33 | cc_library( 34 | name = "argon2_provider", 35 | srcs = ["argon2_provider.cc"], 36 | hdrs = ["argon2_provider.h"], 37 | visibility = ["//visibility:public"], 38 | deps = [ 39 | ":crypto", 40 | "//common", 41 | "@argon2", 42 | "@boost//:interprocess", 43 | "@com_github_google_glog//:glog", 44 | "@iota_lib_cpp", 45 | "@org_iota_common//common/crypto/iss/v1:iss_kerl", 46 | "@org_iota_common//common/crypto/kerl:converter", 47 | "@org_iota_common//common/helpers:sign", 48 | "@org_iota_common//common/trinary:trit_tryte", 49 | ], 50 | ) 51 | 52 | cc_test( 53 | name = "test_crypto", 54 | srcs = glob([ 55 | "tests/**/*.cc", 56 | ]), 57 | deps = [ 58 | ":argon2_provider", 59 | "//common/tests", 60 | "@boost//:interprocess", 61 | "@com_google_googletest//:gtest", 62 | ], 63 | ) 64 | -------------------------------------------------------------------------------- /common/crypto/argon2_provider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_CRYPTO_ARGON2_PROVIDER_H_ 9 | #define COMMON_CRYPTO_ARGON2_PROVIDER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "common/crypto/provider_base.h" 15 | 16 | namespace common { 17 | namespace crypto { 18 | 19 | /// Argon2Provider class. 20 | /// The argon2 provider provides the cryptographic services necessary to 21 | /// obtain new addresses based on salt and sign bundle hashes. 22 | class Argon2Provider : public CryptoProviderBase { 23 | public: 24 | Argon2Provider() = delete; 25 | /// Constructor 26 | /// param[in] salt - the salt that will be used in calculations 27 | explicit Argon2Provider(std::string salt); 28 | 29 | /// Get a new address for a given UUID and the salt 30 | /// param[in] UUID - a UUID 31 | nonstd::optional getAddressForUUID( 32 | const common::crypto::UUID& uuid) const override; 33 | 34 | /// The current security level 35 | /// @return size_t - the security level (1 - 3) 36 | nonstd::optional securityLevel( 37 | const common::crypto::UUID& uuid) const override; 38 | 39 | /// Calculate the seed for a UUID. 40 | /// param[in] UUID - a UUID 41 | /// @return string - the seed 42 | 43 | virtual std::string getSeedFromUUID( 44 | const common::crypto::UUID& uuid) const override; 45 | 46 | protected: 47 | /// Calculate the signature for a UUID and a bundle hash 48 | /// param[in] UUID - a UUID 49 | /// param[in] Hash - a bundleHash 50 | /// @return string - the signature 51 | nonstd::optional doGetSignatureForUUID( 52 | const common::crypto::UUID& uuid, 53 | const common::crypto::Hash& bundleHash) const override; 54 | 55 | private: 56 | /// The salt that will be used all throughout the lifetime of the provider 57 | const std::string _salt; 58 | 59 | static constexpr uint32_t _argon_t_cost{1}; 60 | static constexpr uint32_t _argon_m_cost{1 << 16}; // 64mebibytes 61 | static constexpr uint32_t _argon_parallelism{1}; 62 | }; 63 | 64 | } // namespace crypto 65 | } // namespace common 66 | #endif // COMMON_CRYPTO_ARGON2_PROVIDER_H_ 67 | -------------------------------------------------------------------------------- /common/crypto/manager.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "common/crypto/manager.h" 9 | 10 | namespace common { 11 | namespace crypto { 12 | 13 | CryptoManager& CryptoManager::get() { 14 | static CryptoManager instance; 15 | 16 | return instance; 17 | } 18 | 19 | } // namespace crypto 20 | } // namespace common 21 | -------------------------------------------------------------------------------- /common/crypto/manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_CRYPTO_MANAGER_H_ 9 | #define COMMON_CRYPTO_MANAGER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "common/crypto/provider_base.h" 15 | 16 | namespace common { 17 | namespace crypto { 18 | 19 | /// CryptoManager holds the single instance of a CryptoProvider 20 | class CryptoManager { 21 | private: 22 | /// Constructor 23 | CryptoManager() {} 24 | /// deleted 25 | CryptoManager(CryptoManager const&) = delete; 26 | /// deleted 27 | CryptoManager(CryptoManager&&) = delete; 28 | /// deleted 29 | CryptoManager& operator=(CryptoManager const&) = delete; 30 | /// deleted 31 | CryptoManager& operator=(CryptoManager&&) = delete; 32 | 33 | public: 34 | /// Get the singleton instance 35 | /// @return CryptoManager - the singleton instance of CryptoManager 36 | static CryptoManager& get(); 37 | 38 | /// Set the cryptography provider 39 | /// @param[in] provider - an instance of CryptoProvider 40 | void setProvider(std::unique_ptr provider) { 41 | _provider = std::move(provider); 42 | } 43 | 44 | /// Get the cryptography provider 45 | /// @return CryptoProvider - an instance of CryptoProvider 46 | CryptoProviderBase& provider() { return *_provider; } 47 | 48 | private: 49 | /// The cryptography provider 50 | std::unique_ptr _provider; 51 | }; 52 | 53 | } // namespace crypto 54 | } // namespace common 55 | #endif // COMMON_CRYPTO_MANAGER_H_ 56 | -------------------------------------------------------------------------------- /common/crypto/provider_base.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "common/crypto/provider_base.h" 9 | #include "common/helpers/checksum.h" 10 | 11 | namespace common { 12 | namespace crypto { 13 | 14 | common::crypto::Checksum CryptoProviderBase::calcChecksum( 15 | std::string_view address) const { 16 | char* checksumPtr = iota_checksum(address.data(), address.size(), 17 | common::crypto::Checksum::length()); 18 | auto result = common::crypto::Checksum(checksumPtr); 19 | std::free(checksumPtr); 20 | return result; 21 | } 22 | 23 | nonstd::optional 24 | CryptoProviderBase::verifyAndStripChecksum(const std::string& address) const { 25 | auto addressView = 26 | std::string_view(address).substr(0, common::crypto::Address::length()); 27 | auto checksumView = std::string_view(address).substr( 28 | common::crypto::Address::length(), 29 | common::crypto::Address::length() + common::crypto::Checksum::length()); 30 | if (calcChecksum(addressView).str_view() == checksumView) { 31 | return common::crypto::Address( 32 | address.substr(0, common::crypto::Address::length())); 33 | } 34 | return {}; 35 | } 36 | 37 | } // namespace crypto 38 | } // namespace common 39 | -------------------------------------------------------------------------------- /common/crypto/tests/types.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include "common/crypto/types.h" 9 | 10 | namespace { 11 | 12 | struct TestTag {}; 13 | 14 | using TestArr = common::crypto::TryteArray<12, TestTag>; 15 | 16 | class TrytesArrayTest : public ::testing::Test {}; 17 | 18 | TEST_F(TrytesArrayTest, EnforceCorrectLength) { 19 | EXPECT_THROW(TestArr{""}, std::runtime_error); 20 | } 21 | 22 | TEST_F(TrytesArrayTest, EnforceValidCharacters) { 23 | EXPECT_THROW(TestArr{"WhatTheHell?"}, std::runtime_error); 24 | } 25 | 26 | TEST_F(TrytesArrayTest, AssertInternalRepresentationIsConsistent) { 27 | auto data = 28 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" 29 | "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; 30 | common::crypto::Hash testHash(data); 31 | ASSERT_EQ(testHash.str(), data); 32 | } 33 | 34 | class UUIDTest : public ::testing::Test {}; 35 | 36 | TEST_F(UUIDTest, AssertInternalRepresentationIsConsistent) { 37 | common::crypto::UUID uuidOrig; 38 | std::string_view stringRepresentation = uuidOrig.str_view(); 39 | 40 | auto uuidClone = common::crypto::UUID(stringRepresentation); 41 | 42 | ASSERT_EQ(uuidClone.str(), uuidOrig.str()); 43 | } 44 | 45 | }; // namespace 46 | -------------------------------------------------------------------------------- /common/crypto/types.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "common/crypto/types.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace common { 17 | namespace crypto { 18 | 19 | std::array UUID::generate() { 20 | std::array res; 21 | boost::random::random_device rd; 22 | boost::random::uniform_int_distribution<> index_dist(0, UUID_SIZE - 1); 23 | for (uint32_t i = 0; i < UUID_SIZE; ++i) { 24 | res[i] = BASE64_CHARS[index_dist(rd)]; 25 | } 26 | return res; 27 | } 28 | 29 | std::array UUID::fromStringView( 30 | const std::string_view& sv) { 31 | std::array res; 32 | std::copy(std::begin(sv), std::end(sv), std::begin(res)); 33 | return res; 34 | } 35 | 36 | UUID::UUID() { 37 | try { 38 | _data = std::move(UUID::generate()); 39 | } catch (const std::exception& ex) { 40 | LOG(FATAL) << " Failed in generating UUID: " << ex.what(); 41 | } 42 | } 43 | 44 | UUID::UUID(const std::string_view& sv) : _data(fromStringView(sv)) {} 45 | 46 | std::string UUID::str() const { return std::string(str_view()); } 47 | 48 | std::string_view UUID::str_view() const { 49 | return std::string_view(reinterpret_cast(_data.data()), 50 | UUID_SIZE); 51 | } 52 | 53 | const std::array& UUID::data() const { 54 | return _data; 55 | } 56 | 57 | bool operator==(const common::crypto::UUID& lhs, 58 | const common::crypto::UUID& rhs) { 59 | return lhs.data() == rhs.data(); 60 | } 61 | 62 | bool operator!=(const common::crypto::UUID& lhs, 63 | const common::crypto::UUID& rhs) { 64 | return !(lhs == rhs); 65 | } 66 | } // namespace crypto 67 | } // namespace common 68 | -------------------------------------------------------------------------------- /common/flags.cc: -------------------------------------------------------------------------------- 1 | #include "common/flags.h" 2 | 3 | namespace common { 4 | namespace flags { 5 | 6 | DEFINE_string(salt, "", "Salt for local seed provider"); 7 | DEFINE_string(listenAddress, "0.0.0.0:50051", "address to listen on"); 8 | // Server side credentials 9 | DEFINE_string(sslCert, "/dev/null", "Path to SSL certificate"); 10 | DEFINE_string(sslKey, "/dev/null", "Path to SSL certificate key"); 11 | DEFINE_string(sslCA, "/dev/null", "Path to CA root"); 12 | DEFINE_string(sslDH, "/dev/null", 13 | "Path to Diffie Hellman parameters (when using REST)"); 14 | 15 | DEFINE_string(authMode, "none", "credentials to use. can be {none, ssl}"); 16 | // Argon2 17 | DEFINE_uint32(maxConcurrentArgon2Hash, 4, 18 | "Max number of concurrent Argon2 Hash processes"); 19 | DEFINE_uint32(argon2TCost, 4, "Time cost of Argon2"); 20 | DEFINE_uint32(argon2MCost, 1 << 17, "Memory cost of Argon2 in bytes"); 21 | DEFINE_uint32(argon2Parallelism, 1, 22 | "Number of threads to use in parallel for Argon2"); 23 | DEFINE_uint32(argon2Mode, 2, "Argon2 mode to use: 1=argon2i;2,else=argon2id"); 24 | DEFINE_uint32(keySecLevel, 2, "Security level for IOTA signature"); 25 | 26 | DEFINE_uint32(numThreadsHttp, 4, 27 | "The number of threads the http server should run"); 28 | } // namespace flags 29 | } // namespace common 30 | -------------------------------------------------------------------------------- /common/flags.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_FLAGS_H_ 9 | #define COMMON_FLAGS_H_ 10 | 11 | #include 12 | #include 13 | 14 | namespace common { 15 | namespace flags { 16 | DECLARE_string(salt); 17 | DECLARE_string(listenAddress); 18 | DECLARE_string(sslCert); 19 | DECLARE_string(sslKey); 20 | DECLARE_string(sslCA); 21 | DECLARE_string(authMode); 22 | // Argon2 23 | DECLARE_uint32(maxConcurrentArgon2Hash); 24 | DECLARE_uint32(argon2TCost); 25 | DECLARE_uint32(argon2MCost); 26 | DECLARE_uint32(argon2Parallelism); 27 | DECLARE_uint32(argon2Mode); 28 | // IOTA seeds 29 | DECLARE_uint32(keySecLevel); 30 | // Http server 31 | DECLARE_uint32(numThreadsHttp); 32 | DECLARE_string(sslDH); 33 | } // namespace flags 34 | } // namespace common 35 | 36 | #endif // COMMON_FLAGS_H_ -------------------------------------------------------------------------------- /common/grpc_server_base.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include "common/common.h" 11 | #include "common/grpc_server_base.h" 12 | 13 | namespace common { 14 | 15 | void GrpcServerBase::runAndWait() { _server->Wait(); } 16 | 17 | std::shared_ptr GrpcServerBase::makeCredentials( 18 | const std::string& authMode, const std::string& sslCertPath, 19 | const std::string& sslKeyPath, const std::string& sslCAPath) { 20 | LOG(INFO) << "Using auth mode: " << authMode; 21 | if (authMode == "none") { 22 | return grpc::InsecureServerCredentials(); 23 | } else if (authMode == "ssl") { 24 | grpc::SslServerCredentialsOptions options; 25 | 26 | grpc::SslServerCredentialsOptions::PemKeyCertPair keycert = { 27 | readFile(sslKeyPath), readFile(sslCertPath)}; 28 | 29 | options.pem_key_cert_pairs.push_back(keycert); 30 | options.pem_root_certs = readFile(sslCAPath); 31 | options.client_certificate_request = 32 | GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY; 33 | return grpc::SslServerCredentials(options); 34 | } 35 | 36 | LOG(FATAL) << "Unknown auth mode: " << authMode; 37 | } 38 | } // namespace common 39 | -------------------------------------------------------------------------------- /common/grpc_server_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_GRPC_SERVER_BASE_H_ 9 | #define COMMON_GRPC_SERVER_BASE_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "server_base.h" 15 | #include "grpc++/grpc++.h" 16 | 17 | namespace common { 18 | 19 | class GrpcServerBase : public ServerBase { 20 | public: 21 | /// Runs the service and waits for requests 22 | virtual void runAndWait() override ; 23 | 24 | protected: 25 | std::unique_ptr _server; 26 | std::shared_ptr makeCredentials( 27 | const std::string& authMode, const std::string& sslCertPath, 28 | const std::string& sslKeyPath, const std::string& sslCAPath); 29 | }; 30 | } // namespace common 31 | 32 | #endif // COMMON_GRPC_SERVER_BASE_H_ 33 | -------------------------------------------------------------------------------- /common/http_server_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_HTTP_SERVER_BASE_H_ 9 | #define COMMON_HTTP_SERVER_BASE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "server_base.h" 22 | 23 | namespace common { 24 | 25 | class HttpServerBase : public ServerBase { 26 | public: 27 | typedef enum { OK = 0, COMMAND_NOT_FOUND, WRONG_REQUEST_FORMAT } ErrorCode; 28 | /// Runs the service and waits for requests 29 | virtual void runAndWait() override; 30 | virtual ErrorCode handleRequestImpl(std::string_view request_body, 31 | std::string& response) = 0; 32 | private: 33 | static void setupCredentials(boost::asio::ssl::context& ctx); 34 | }; 35 | } // namespace common 36 | 37 | #endif // COMMON_HTTP_SERVER_BASE_H_ 38 | -------------------------------------------------------------------------------- /common/server_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_SERVER_BASE_H_ 9 | #define COMMON_SERVER_BASE_H_ 10 | 11 | #include "common/flags.h" 12 | 13 | namespace common { 14 | 15 | class ServerBase { 16 | public: 17 | /// Creates and initializes the API interface. 18 | virtual void initialize() = 0; 19 | /// Runs the service and waits for requests 20 | virtual void runAndWait() = 0; 21 | }; 22 | } // namespace common 23 | 24 | #endif // COMMON_SERVER_BASE_H_ 25 | -------------------------------------------------------------------------------- /common/stats/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "stats", 3 | srcs = glob(["**/*.cc"]), 4 | hdrs = glob(["**/*.h"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//common/crypto:types", 8 | "@com_github_google_glog//:glog", 9 | ], 10 | ) 11 | -------------------------------------------------------------------------------- /common/stats/session.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "common/stats/session.h" 9 | 10 | namespace common { 11 | std::ostream& operator<<(std::ostream& os, const ClientSession& session) { 12 | os << session.to_str(); 13 | return os; 14 | } 15 | } // namespace common 16 | -------------------------------------------------------------------------------- /common/stats/session.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef COMMON_STATS_SESSION_H_ 9 | #define COMMON_STATS_SESSION_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include "common/crypto/types.h" 18 | 19 | namespace common { 20 | class ClientSession { 21 | public: 22 | ClientSession() : _tag(crypto::UUID().str()), _str(rep_str()) {} 23 | 24 | ~ClientSession() { LOG(INFO) << *this << "destroyed."; } 25 | 26 | const std::string& tag() const { return _tag; } 27 | const std::string& to_str() const { return _str; } 28 | 29 | private: 30 | friend std::ostream& operator<<(std::ostream& os, const ClientSession& stats); 31 | 32 | std::string rep_str() const { 33 | std::ostringstream ostr; 34 | ostr << "ClientSession(" << _tag << ") "; 35 | return ostr.str(); 36 | } 37 | 38 | const std::string _tag; 39 | const std::string _str; 40 | }; 41 | 42 | }; // namespace common 43 | 44 | #endif // COMMON_STATS_SESSION_H_ 45 | -------------------------------------------------------------------------------- /common/tests/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "tests", 3 | srcs = ["runner.cc"], 4 | visibility = ["//visibility:public"], 5 | deps = [ 6 | "//common/crypto:argon2_provider", 7 | "//common/stats", 8 | "@com_github_google_glog//:glog", 9 | "@com_google_googletest//:gtest", 10 | ], 11 | ) 12 | -------------------------------------------------------------------------------- /common/tests/runner.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char** argv) { 11 | google::InstallFailureSignalHandler(); 12 | google::InitGoogleLogging("commands-tests"); 13 | testing::InitGoogleMock(&argc, argv); 14 | gflags::ParseCommandLineFlags(&argc, &argv, true); 15 | 16 | return RUN_ALL_TESTS(); 17 | } 18 | -------------------------------------------------------------------------------- /docker/BUILD: -------------------------------------------------------------------------------- 1 | load("@io_bazel_rules_docker//cc:image.bzl", "cc_image") 2 | 3 | cc_image( 4 | name = "hub", 5 | base = "@ubuntu_base//image", 6 | binary = "//hub:hub", 7 | repository = "iota/hub/docker", 8 | visibility = ["//visibility:public"], 9 | ) 10 | 11 | cc_image( 12 | name = "signing_server", 13 | base = "@ubuntu_base//image", 14 | binary = "//signing_server:signing_server", 15 | repository = "iota/hub/docker", 16 | visibility = ["//visibility:public"], 17 | ) 18 | -------------------------------------------------------------------------------- /docs/checksum_validation.md: -------------------------------------------------------------------------------- 1 | # HIP-002: Checksum validation 2 | 3 | ## Problem description 4 | Users need an address's checksum to send funds to it. 5 | Also, when withdrawing, due to some errors, whether it is wrong address given 6 | by user or wrong use of hub on the exchange side, we wouldn't want the transaction 7 | to happen in the first place, to keep everyone happy. 8 | 9 | ## Proposed solution 10 | 11 | 1. UserWithdraw will now validate provided address is valid using checksum. 12 | 13 | 2. GetDepositAddress will return the checksum 14 | 15 | ## Proposed implemntation 16 | 17 | modify existing `message` objects: 18 | ```proto 19 | // add `checksum` to GetDepositAddressReply: 20 | message GetDepositAddressReply { 21 | // Newly created deposit address 22 | string address = 1; 23 | } 24 | // Provided address should contain checksum 25 | message UserWithdrawRequest { 26 | string userId = 1; 27 | // Address the user requests payout to. Should be without checksum. 28 | string payoutAddress = 2; 29 | // Requested withdrawal amount 30 | uint64 amount = 3; 31 | // Tag for withdrawal 32 | string tag = 4; 33 | } 34 | enum ErrorCode { 35 | // Provided `payoutAddress` first 81 trytes 36 | // does not checksum to the last 9 37 | CHECKSUM_INVALID = 9; 38 | } 39 | 40 | ``` 41 | declare/instantiate types in `crypto/types.h`: 42 | 43 | struct ChecksumTag {}; 44 | using Checksum = TryteArray<9, ChecksumTag>; 45 | 46 | Add methods: 47 | 48 | `Checksum calcChecksum(const string& address)` 49 | `nonstd::optional
verifyAndStripChecksum(const string& address)` 50 | 51 | 52 | that will check if first 81 trytes checksums to last 9 of `addressWithChecksum` 53 | and will only return an address if it does checksum 54 | so, in case it does not withdrawal will fail 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /docs/getting_started.md: -------------------------------------------------------------------------------- 1 | # IOTA Hub: Getting started. 2 | 3 | ## Before we start: 4 | - Hub is not an IOTA node, it is a tool for managing transfers from/to addresses in a simple and secure manner 5 | - User should send tokens to a deposit address only once, since deposit addresses are swept and aren't reusable 6 | - In case user sent tokens to a deposit address that has been swept, we offer a mechanism to recover the funds (see docs/hip/001-sign_bundle.md) 7 | 8 | ## Building the hub 9 | - `bazel build -c opt //hub:hub` 10 | 11 | ## Building signing_server (for remote signing_server) 12 | - `bazel build -c opt //signing_server` 13 | 14 | ## Setup the database (this example is using MariaDB) 15 | - Install `MariaDB` (e.g. via Docker) 16 | - Import schemas: 17 | - `mysql -h127.0.0.1 --user root -ppassword < schema/schema.sql` 18 | - `mysql -h127.0.0.1 --user root -ppassword < schema/triggers.mariadb.sql` 19 | 20 | ## Running the hub 21 | - `./bazel-bin/hub/hub --salt yoursaltcharachters --apiAddress your_iri_node_uri --db db_name --dbUser your_user --dbPassword user_password --monitorInterval xxx --attachmentInterval yyy --sweepInterval zzz` 22 | - For detailed explanation about program arguments, see `README.md` or start with `--help` 23 | - For running the hub with remote salt provider (`--signingMode=remote`) run the `signing_provider` first 24 | 25 | ## Running the signing_server 26 | - `./bazel-bin/signing_server/signing_server --salt abcdefghijklmnopqrstuvwxyz --authMode=ssl -sslKey docs/ssl/server.key -sslCert docs/ssl/server.crt -sslCA docs/ssl/ca.crt --listenAddress=localhost:50052` 27 | 28 | ### Run via Docker 29 | You can build and run a docker image for `RPCHub` via `bazel run -c opt //docker:hub` 30 | 31 | ## Calling client commands 32 | - The Hub exposes both gRPC (https://grpc.io/docs/tutorials/) and REST apis 33 | - GRPC: Methods and arguments are available under proto/hub.proto (methods) and proto/messages.proto (request/response types) 34 | - REST: [HTTP_REST_API](http_rest_api.md) 35 | -------------------------------------------------------------------------------- /docs/hip/001-sign_bundle.md: -------------------------------------------------------------------------------- 1 | # HIP-001: SignBundle 2 | 3 | ## Problem description 4 | Even though exchanges warn against this explicitly, might end up sending tokens to addresses that have already been used as inputs for a sweep. 5 | Due to address security reasons, the Hub does not monitor such addresses any longer. 6 | However, when large amounts of funds are at risk, users might sue exchanges / go to the press / similar. To prevent this from happening, an exchange must have 7 | a means to access the funds (i.e. send back to the user). 8 | 9 | ## Proposed solution 10 | Offer the following gRPC method call that can be enabled via a runtime flag but is *disabled by default*. 11 | 12 | ```proto 13 | // add to ErrorCode: 14 | enum ErrorCode { 15 | // Address is unknown or has not been used as input for a sweep 16 | ADDRESS_NOT_ELIGIBLE; 17 | // The authentication token could not be verified. 18 | INVALID_AUTHENTICATION; 19 | } 20 | 21 | message SignBundleRequest { 22 | // The Hub-owned IOTA address that should be signed. (without checksum) 23 | string address = 1; 24 | // The bundle hash that should be signed. 25 | string bundleHash = 2; 26 | // Authentication token 27 | string authentication = 3; 28 | } 29 | 30 | message SignBundleReply { 31 | // The computed signature 32 | string signature = 1; 33 | } 34 | 35 | service Hub { 36 | // Reveals the seed for a given user address. 37 | rpc SignBundle(SignBundleRequest) returns SignBundleResponse); 38 | } 39 | ``` 40 | 41 | Internally, the call will: 42 | 1. Check that address was used in sweep before. 43 | 2. Verify authentication token. 44 | 3. Calculate & return signature 45 | 46 | If an exchange wants to provide a custom audit system integration, they'll need to implement the following interface and register it at startup in their local fork. 47 | 48 | ```c++ 49 | // @file hub/auth/provider.h 50 | 51 | namespace hub { 52 | namespace auth { 53 | 54 | enum AuthContext { 55 | SIGN_BUNDLE = 0; 56 | }; 57 | 58 | class AuthProvider { 59 | public: 60 | virtual bool validateToken(const std::string& token) = 0; 61 | }; 62 | 63 | } 64 | } 65 | 66 | ``` 67 | 68 | ## Motivation 69 | ### Authentication payload 70 | Some exchanges might have internal safeguards to prevent rogue internal actors from accessing secrets. Therefore, the Hub needs to be able to integrate with these by exposing an interface they can program against. 71 | 72 | ## Questions 73 | 1. Should the call be able to be called multiple times? 74 | 2. Which authentication method should be provided by default? 75 | 1. Password 76 | 2. HMAC 77 | 78 | 79 | -------------------------------------------------------------------------------- /docs/hip/template.md: -------------------------------------------------------------------------------- 1 | # HIP-XXX: Name 2 | 3 | ## Problem description 4 | 5 | ## Proposed solution 6 | 7 | ## Motivation 8 | 9 | ## Questions 10 | 11 | -------------------------------------------------------------------------------- /docs/pull_request_template.md: -------------------------------------------------------------------------------- 1 | <> 2 | 3 | # Test Plan: 4 | <> 5 | -------------------------------------------------------------------------------- /docs/python/.gitignore: -------------------------------------------------------------------------------- 1 | proto/ -------------------------------------------------------------------------------- /docs/python/README.md: -------------------------------------------------------------------------------- 1 | # Example Python client code 2 | First generate protobuf bindings via `./generate_proto.sh` 3 | -------------------------------------------------------------------------------- /docs/python/argon2_authentication_token.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argon2 3 | 4 | #Install argon2_cffi: 5 | #https://argon2-cffi.readthedocs.io/en/stable/installation.html 6 | 7 | def argon2Token(message, salt): 8 | 9 | res = argon2.low_level.hash_secret(message, salt, time_cost=4, memory_cost=17, parallelism=1, hash_len=64, type=argon2.low_level.Type.ID) 10 | 11 | token = res.split("$",4) 12 | 13 | return token[4][:43] 14 | 15 | def main(): 16 | 17 | bundleHash = b"9999999999999999999999999999999999999999999999999999999D9999999999999999999999999" 18 | address = b"999ZZS9LS99LPKLDGHTU999999PP9KH9K9JH999999PLR99IO999T999H9999999999HHL999YU999ZBA" 19 | salt = b"El6vxEO4rR009/U/u70SgPa6C7GVZQzXZOUQrkMnXFI" 20 | 21 | 22 | print(argon2Token(bundleHash + address, salt) == b"RWw2dnhFTzRyUjAwOS9VL3U3MFNnUGE2QzdHVlpRelh") 23 | 24 | if __name__ == '__main__': 25 | main() 26 | 27 | -------------------------------------------------------------------------------- /docs/python/generate_proto.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python -m grpc_tools.protoc --python_out=. --proto_path=../../ --grpc_python_out=. ../../proto/messages.proto ../../proto/hub.proto 4 | -------------------------------------------------------------------------------- /docs/python/ssl_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import grpc 3 | 4 | import proto.hub_pb2_grpc as hub 5 | import proto.messages_pb2 as msg 6 | 7 | 8 | def main(): 9 | host = 'localhost' 10 | port = 50051 11 | 12 | with open('../ssl/client.crt', 'rb') as f: 13 | client_cert = f.read() 14 | with open('../ssl/client.key', 'rb') as f: 15 | client_key = f.read() 16 | with open('../ssl/ca.crt', 'rb') as f: 17 | chain = f.read() 18 | 19 | credentials = grpc.ssl_channel_credentials(root_certificates=chain, 20 | private_key=client_key, 21 | certificate_chain=client_cert) 22 | channel = grpc.secure_channel('{}:{}'.format(host, port), credentials) 23 | 24 | stub = hub.HubStub(channel) 25 | 26 | req = msg.CreateUserRequest(userId='a') 27 | stub.CreateUser(req) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /docs/secure_server.md: -------------------------------------------------------------------------------- 1 | # Securing Hub/Signing_Server (The example below is for hub but could easily adjusted to signing_server as well) 2 | 3 | ## Connect to Hub via SSL 4 | 1. Create certificates, see example scripts in `docs/ssl` for further guidance. *The server CN needs to match the actual server's hostname!* 5 | 2. Start Hub in correct authMode: `--authMode ssl --sslKey docs/ssl/server.key --sslCert docs/ssl/server.crt --sslCA docs/ssl/ca.crt` 6 | 7 | **Please note that if you're running the hub via `bazel run`, these paths need to be absolute!** 8 | 3. Configure your Hub client to use SSL, see the provided Python example for further guidance. If you're using grpcc for testing, this might be helpful: 9 | `grpcc -a 'localhost:50051' -p proto/hub.proto --root_cert path-to/ca.crt --private_key path-to/client.key --cert_chain path-to/client.crt` 10 | -------------------------------------------------------------------------------- /docs/ssl/.gitignore: -------------------------------------------------------------------------------- 1 | *.crt 2 | *.key 3 | *.csr -------------------------------------------------------------------------------- /docs/ssl/grpc/01_generate_ca.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | openssl genrsa -passout pass:1234 -des3 -out ca.key 4096 4 | openssl req -new -x509 -passin pass:1234 -days 365 -key ca.key -out ca.crt -subj "/C=DE/ST=Berlin/L=Berlin/O=HUB User/OU=HUB User/CN=HUB Root CA" 5 | 6 | -------------------------------------------------------------------------------- /docs/ssl/grpc/02_generate_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Generate valid Server Key/Cert 4 | openssl genrsa -passout pass:1234 -des3 -out server.key 4096 5 | openssl req -passin pass:1234 -new -key server.key -out server.csr -subj "/C=DE/ST=Berlin/L=Berlin/O=HUB/OU=Server/CN=localhost" 6 | openssl x509 -req -passin pass:1234 -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt 7 | 8 | # Remove passphrase from the Server Key 9 | openssl rsa -passin pass:1234 -in server.key -out server.key 10 | 11 | cat ca.crt server.crt > server_chain.crt 12 | -------------------------------------------------------------------------------- /docs/ssl/grpc/03_generate_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Generate valid Client Key/Cert 4 | openssl genrsa -passout pass:1234 -des3 -out client.key 4096 5 | openssl req -passin pass:1234 -new -key client.key -out client.csr -subj "/C=DE/ST=Berlin/L=Berlin/O=HUB/OU=Client/CN=localhost" 6 | openssl x509 -passin pass:1234 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt 7 | 8 | # Remove passphrase from Client Key 9 | openssl rsa -passin pass:1234 -in client.key -out client.key 10 | -------------------------------------------------------------------------------- /docs/ssl/rest/generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # in order to be able to test commands with https support using curl and a self 4 | # signed certificate, use the `-k` flag 5 | 6 | openssl dhparam -out dh.pem 2048 7 | openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days - nodes 365 -sub -subj "/CN=localhost" -------------------------------------------------------------------------------- /hooks/pre-commit/01-buildifier-check: -------------------------------------------------------------------------------- 1 | ../scripts/buildifier_check -------------------------------------------------------------------------------- /hooks/pre-commit/02-cpplint: -------------------------------------------------------------------------------- 1 | ../scripts/cpplint -------------------------------------------------------------------------------- /hooks/pre-commit/03-format-check: -------------------------------------------------------------------------------- 1 | ../scripts/format_check -------------------------------------------------------------------------------- /hooks/scripts/buildifier_check: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | buildifier -showlog -mode=check $(git ls-files $(git rev-parse --show-toplevel) | grep -E "WORKSPACE|BUILD(\.(bazel|bzl))?\$") 4 | -------------------------------------------------------------------------------- /hooks/scripts/cpplint: -------------------------------------------------------------------------------- 1 | ../../tools/cpplint -------------------------------------------------------------------------------- /hooks/scripts/format_check: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | root=$(git rev-parse --show-toplevel) 4 | status=0 5 | for file in $(git diff --staged --name-only | grep -E "\.(c|cc|cpp|h|hh|hpp)\$") 6 | do 7 | filepath="$root/$file" 8 | output=$(diff <(cat $filepath) <(clang-format -style=file -fallback-style=none $filepath)) 9 | if [ $? -ne 0 ] 10 | then 11 | echo -e "\nFile \""$file"\" is not compliant with the coding style" 12 | echo "$output" 13 | status=1 14 | fi 15 | done 16 | exit $status 17 | -------------------------------------------------------------------------------- /hub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/hub/9df503d4def3021b082ba7aaaace7a9265e2ba18/hub.png -------------------------------------------------------------------------------- /hub/BUILD: -------------------------------------------------------------------------------- 1 | cc_binary( 2 | name = "hub", 3 | srcs = ["main.cc"], 4 | visibility = ["//visibility:public"], 5 | deps = [ 6 | "//hub/db", 7 | "//hub/server", 8 | "@com_github_gflags_gflags//:gflags", 9 | "@com_github_google_glog//:glog", 10 | ], 11 | ) 12 | -------------------------------------------------------------------------------- /hub/auth/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "auth", 3 | srcs = ["manager.cc"], 4 | hdrs = [ 5 | "manager.h", 6 | "provider.h", 7 | ], 8 | visibility = ["//visibility:public"], 9 | deps = [ 10 | ], 11 | ) 12 | 13 | cc_library( 14 | name = "dummy_provider", 15 | hdrs = ["dummy_provider.h"], 16 | visibility = ["//visibility:public"], 17 | deps = [ 18 | ":auth", 19 | "@com_github_google_glog//:glog", 20 | ], 21 | ) 22 | 23 | cc_library( 24 | name = "hmac_provider", 25 | srcs = glob([ 26 | "hmac_provider.*", 27 | "sign_bundle_context.*", 28 | ]), 29 | hdrs = ["hmac_provider.h"], 30 | visibility = ["//visibility:public"], 31 | deps = [ 32 | ":auth", 33 | "//common", 34 | "//common/crypto", 35 | "@argon2", 36 | "@com_github_google_glog//:glog", 37 | ], 38 | ) 39 | 40 | cc_test( 41 | name = "test_hmac_provider", 42 | srcs = glob([ 43 | "tests/**/*.cc", 44 | ]), 45 | deps = [ 46 | ":hmac_provider", 47 | "//hub/tests", 48 | "@com_google_googletest//:gtest", 49 | ], 50 | ) 51 | -------------------------------------------------------------------------------- /hub/auth/dummy_provider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_AUTH_DUMMY_PROVIDER_H_ 9 | #define HUB_AUTH_DUMMY_PROVIDER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "hub/auth/provider.h" 15 | 16 | namespace hub { 17 | namespace auth { 18 | 19 | /// DummyProvider class. 20 | /// The dummy provider accepts any token. 21 | class DummyProvider : public AuthProvider { 22 | public: 23 | /// Constructor 24 | DummyProvider() {} 25 | 26 | bool validateToken(const AuthContext& context, 27 | const std::string& token) noexcept override { 28 | return true; 29 | } 30 | }; 31 | 32 | } // namespace auth 33 | } // namespace hub 34 | #endif // HUB_AUTH_DUMMY_PROVIDER_H_ 35 | -------------------------------------------------------------------------------- /hub/auth/hmac_provider.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | #include 8 | #include 9 | #include 10 | 11 | #include "common/flags.h" 12 | #include "hub/auth/hmac_provider.h" 13 | 14 | namespace hub { 15 | namespace auth { 16 | 17 | HMACProvider::HMACProvider(const std::string& key) : _key(key) { 18 | if (_key.size() > KEY_SIZE) { 19 | _key.resize(KEY_SIZE); 20 | } else if (_key.size() < KEY_SIZE) { 21 | throw std::runtime_error( 22 | __FUNCTION__ + 23 | std::string("Provided HMAC key has wrong size (expected size: ") + 24 | std::to_string(KEY_SIZE) + 25 | " observed size: " + std::to_string(_key.size()) + ")"); 26 | } 27 | } 28 | HMACProvider::~HMACProvider() { 29 | _key.replace(0, _key.size(), _key.size(), '0'); 30 | } 31 | 32 | bool HMACProvider::validateToken(const AuthContext& context, 33 | const std::string& token) noexcept { 34 | char encoded[HASH_SIZE * 6]; 35 | 36 | if (argon2id_hash_encoded( 37 | common::flags::FLAGS_argon2TCost, common::flags::FLAGS_argon2MCost, 38 | common::flags::FLAGS_argon2Parallelism, context.message().c_str(), 39 | context.message().size(), _key.c_str(), _key.size(), HASH_SIZE * 2, 40 | encoded, HASH_SIZE * 6) != ARGON2_OK) { 41 | LOG(ERROR) << "Failed in " << __FUNCTION__; 42 | return false; 43 | } 44 | 45 | return token.compare(stripEncodedPrefix(encoded)) == 0; 46 | } 47 | 48 | std::string_view HMACProvider::stripEncodedPrefix(const std::string_view& e) { 49 | // strip prefix from encoded 50 | // Encoded example with prefix: 51 | // $argon2id$v=19$m=131072,t=4,p=1$c29tZXNhbHQ$xLJXnoh1+mb/bqTS72pL+pBbH1+sih7KFiZV1k4fdmM 52 | // After stripping: c29tZXNhbHQ$xLJXnoh1+mb/bqTS72pL+pBbH1+sih7KFiZV1k4fdmM 53 | 54 | static constexpr uint8_t NUM_DOLLAR_SIGNS_IN_PREFIX = 4; 55 | 56 | auto prefixSize = 0; 57 | uint8_t dollarSignCounter = 0; 58 | std::string_view curr(e); 59 | while (dollarSignCounter < NUM_DOLLAR_SIGNS_IN_PREFIX) { 60 | curr = e.substr(prefixSize, KEY_SIZE); 61 | auto pos = curr.find_first_of('$'); 62 | if (pos == std::string::npos) { 63 | LOG(ERROR) << "Failed in " << __FUNCTION__; 64 | break; 65 | } 66 | curr = curr.substr(0, pos + 1); 67 | prefixSize += curr.size(); 68 | dollarSignCounter++; 69 | } 70 | 71 | return e.substr(prefixSize, KEY_SIZE); 72 | } 73 | 74 | } // namespace auth 75 | } // namespace hub 76 | -------------------------------------------------------------------------------- /hub/auth/hmac_provider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_AUTH_HMAC_PROVIDER_H_ 9 | #define HUB_AUTH_HMAC_PROVIDER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "hub/auth/provider.h" 16 | #include "hub/auth/sign_bundle_context.h" 17 | 18 | namespace hub { 19 | namespace auth { 20 | 21 | /// DummyProvider class. 22 | /// The dummy provider accepts any token. 23 | class HMACProvider : public AuthProvider { 24 | public: 25 | /// 64bit based characters (43 *64bits = 258bits) 26 | constexpr static uint16_t KEY_SIZE = 43; 27 | /// 64bit based characters (43 *64bits = 258bits) 28 | constexpr static uint16_t HASH_SIZE = 43; 29 | /// Constructor 30 | explicit HMACProvider(const std::string& key); 31 | ~HMACProvider(); 32 | 33 | bool validateToken(const AuthContext& context, 34 | const std::string& token) noexcept override; 35 | 36 | private: 37 | std::string_view stripEncodedPrefix(const std::string_view& encoded); 38 | 39 | std::string _key; 40 | }; 41 | 42 | } // namespace auth 43 | } // namespace hub 44 | #endif // HUB_AUTH_HMAC_PROVIDER_H_ 45 | -------------------------------------------------------------------------------- /hub/auth/manager.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/auth/manager.h" 9 | 10 | namespace hub { 11 | namespace auth { 12 | 13 | AuthManager& AuthManager::get() { 14 | static AuthManager instance; 15 | 16 | return instance; 17 | } 18 | 19 | } // namespace auth 20 | } // namespace hub 21 | -------------------------------------------------------------------------------- /hub/auth/manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_AUTH_MANAGER_H_ 9 | #define HUB_AUTH_MANAGER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "hub/auth/provider.h" 15 | 16 | namespace hub { 17 | namespace auth { 18 | 19 | /// AuthManager holds the single instance of a AuthProvider 20 | class AuthManager { 21 | private: 22 | /// Constructor 23 | AuthManager() {} 24 | /// deleted 25 | AuthManager(AuthManager const&) = delete; 26 | /// deleted 27 | AuthManager(AuthManager&&) = delete; 28 | /// deleted 29 | AuthManager& operator=(AuthManager const&) = delete; 30 | /// deleted 31 | AuthManager& operator=(AuthManager&&) = delete; 32 | 33 | public: 34 | /// Get the singleton instance 35 | /// @return AuthManager - the singleton instance of AuthManager 36 | static AuthManager& get(); 37 | 38 | /// Set the authentication provider 39 | /// @param[in] provider - an instance of AuthProvider 40 | void setProvider(std::unique_ptr provider) { 41 | _provider = std::move(provider); 42 | } 43 | 44 | /// Get the authentication provider 45 | /// @return AuthProvider - an instance of AuthProvider 46 | AuthProvider& provider() { return *_provider; } 47 | 48 | private: 49 | /// The authentication provider 50 | std::unique_ptr _provider; 51 | }; 52 | 53 | } // namespace auth 54 | } // namespace hub 55 | #endif // HUB_AUTH_MANAGER_H_ 56 | -------------------------------------------------------------------------------- /hub/auth/provider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_AUTH_PROVIDER_H_ 9 | #define HUB_AUTH_PROVIDER_H_ 10 | 11 | #include 12 | 13 | namespace hub { 14 | namespace auth { 15 | 16 | class AuthContext { 17 | public: 18 | virtual const std::string& message() const noexcept = 0; 19 | }; 20 | 21 | /// AuthProvider abstract class. 22 | /// Provides facilities to authenticate certain requests. 23 | class AuthProvider { 24 | public: 25 | /// Destructor 26 | virtual ~AuthProvider() {} 27 | 28 | /// Attempts to validate a token. 29 | /// param[in] the token context 30 | /// param[in] token the token 31 | /// returns true if token was valid 32 | virtual bool validateToken(const AuthContext& context, 33 | const std::string& token) noexcept = 0; 34 | }; 35 | 36 | } // namespace auth 37 | } // namespace hub 38 | #endif // HUB_AUTH_PROVIDER_H_ 39 | -------------------------------------------------------------------------------- /hub/auth/sign_bundle_context.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/auth/sign_bundle_context.h" 9 | 10 | namespace hub { 11 | namespace auth { 12 | 13 | SignBundleContext::SignBundleContext(const common::crypto::Hash& bundleHash, 14 | const common::crypto::Address& address) { 15 | _message = bundleHash.str() + address.str(); 16 | } 17 | const std::string& SignBundleContext::message() const noexcept { 18 | return _message; 19 | } 20 | } // namespace auth 21 | } // namespace hub 22 | -------------------------------------------------------------------------------- /hub/auth/sign_bundle_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_AUTH_SIGN_BUNDLE_CONTEXT_H_ 9 | #define HUB_AUTH_SIGN_BUNDLE_CONTEXT_H_ 10 | 11 | #include 12 | 13 | #include "common/crypto/types.h" 14 | #include "hub/auth/provider.h" 15 | 16 | namespace hub { 17 | namespace auth { 18 | 19 | class SignBundleContext : public AuthContext { 20 | public: 21 | SignBundleContext(const common::crypto::Hash& bundleHash, 22 | const common::crypto::Address& address); 23 | const std::string& message() const noexcept override; 24 | 25 | private: 26 | std::string _message; 27 | }; 28 | 29 | } // namespace auth 30 | } // namespace hub 31 | #endif // HUB_AUTH_SIGN_BUNDLE_CONTEXT_H_ 32 | -------------------------------------------------------------------------------- /hub/auth/tests/hmac_provider.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "common/crypto/types.h" 10 | #include "hub/auth/hmac_provider.h" 11 | #include "hub/db/db.h" 12 | #include "hub/tests/runner.h" 13 | 14 | using namespace hub; 15 | using namespace hub::auth; 16 | 17 | namespace { 18 | 19 | class HMACProviderTest : public hub::Test {}; 20 | 21 | TEST_F(HMACProviderTest, EnforceKeyLength) { 22 | EXPECT_THROW(HMACProvider{std::string("abcdefghijklmnop")}, 23 | std::runtime_error); 24 | } 25 | 26 | TEST_F(HMACProviderTest, ShouldValidateOnCorrectToken) { 27 | std::string key = "El6vxEO4rR009/U/u70SgPa6C7GVZQzXZOUQrkMnXFI"; 28 | HMACProvider provider(key); 29 | 30 | common::crypto::Hash bundleHash( 31 | "9999999999999999999999999999999999999999999999999999999D9999999999999999" 32 | "999999999"); 33 | common::crypto::Address address( 34 | "999ZZS9LS99LPKLDGHTU999999PP9KH9K9JH999999PLR99IO999T999H9999999999HHL99" 35 | "9YU999ZBA"); 36 | auth::SignBundleContext context(bundleHash, address); 37 | 38 | constexpr auto token = "RWw2dnhFTzRyUjAwOS9VL3U3MFNnUGE2QzdHVlpRelh"; 39 | 40 | ASSERT_TRUE(provider.validateToken(context, token)); 41 | } 42 | 43 | TEST_F(HMACProviderTest, ShouldRejectOnIncorrectToken) { 44 | std::string key = "El6vxEO4rR009/U/u70SgPa6C7GVZQzXZOUQrkMnXFI"; 45 | HMACProvider provider(key); 46 | 47 | common::crypto::Hash bundleHash( 48 | "9999999999999999999999999999999999999999999999999999999D9999999999999999" 49 | "999999999"); 50 | common::crypto::Address address( 51 | "999ZZS9LS99LPKLDGHTU999999PP9KH9K9JH999999PLR99IO999T999H9999999999HHL99" 52 | "9YU999ZBA"); 53 | auth::SignBundleContext context(bundleHash, address); 54 | 55 | // changed last character 56 | constexpr auto token = "RWw2dnhFTzRyUjAwOS9VL3U3MFNnUGE2QzdHVlpRelz"; 57 | 58 | ASSERT_FALSE(provider.validateToken(context, token)); 59 | } 60 | 61 | }; // namespace 62 | -------------------------------------------------------------------------------- /hub/bundle/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "bundle_utils", 3 | srcs = ["bundle_utils.cc"], 4 | hdrs = ["bundle_utils.h"], 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//common/crypto", 8 | "//hub/db", 9 | "@com_github_gflags_gflags//:gflags", 10 | "@com_github_google_glog//:glog", 11 | "@org_iota_common//common/model:bundle", 12 | "@org_iota_common//common/trinary:flex_trit", 13 | "@org_iota_common//utils:bundle_miner", 14 | ], 15 | ) 16 | -------------------------------------------------------------------------------- /hub/bundle/bundle_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_BUNDLE_CREATE_BUNDLE_H_ 9 | #define HUB_BUNDLE_CREATE_BUNDLE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "common/crypto/types.h" 20 | #include "hub/db/types.h" 21 | 22 | DECLARE_uint32(numBundlesToMine); 23 | 24 | namespace hub { 25 | namespace bundle_utils { 26 | 27 | /// Compute and serialize a bundle made up of all the deposits and withdrawals 28 | /// identified during the sweep. 29 | /// @param[in] deposits - a list of deposit transactions 30 | /// @param[in] hubInputs - a list of internal transfers 31 | /// @param[in] withdrawals - a list of withdrawal transactions 32 | /// @param[in] hubOutput - a list of db::TransferOutput structures 33 | /// @param[in] alreadySignedBundleHashes - if not empty, this means we should 34 | /// force signature and mine for a bundle an already spent address 35 | /// @return a std::tuple containing 36 | /// - the bundle hash 37 | /// - the serialized bundle 38 | std::tuple createBundle( 39 | const std::vector& deposits, 40 | const std::vector& hubInputs, 41 | const std::vector& withdrawals, 42 | const nonstd::optional hubOutputOptional, 43 | const std::vector& alreadySignedBundleHashes = {}); 44 | 45 | /// Persist the bundle data to database 46 | /// identified during the sweep. 47 | /// @param[in] bundle - the bundle hash and its serialized value 48 | /// @param[in] deposits - a list of deposit transactions 49 | /// @param[in] hubInputs - a list of internal transfers 50 | /// @param[in] withdrawals - a list of withdrawal transactions 51 | /// @param[in] hubOutput - the hub address into which the remainder is 52 | /// deposited 53 | void persistToDatabase(std::tuple bundle, 54 | const std::vector& deposits, 55 | const std::vector& hubInputs, 56 | const std::vector& withdrawals, 57 | const nonstd::optional hubOutput); 58 | 59 | /// Creates a new hub address to which funds that remain after a transfer 60 | /// can be moved. 61 | /// @param[in] remainder 62 | /// @return a db::TransferOutput structure containing 63 | /// - the new hub address 64 | /// - the id of the new hub address 65 | /// - the remainder 66 | hub::db::TransferOutput getHubOutput(uint64_t remainder); 67 | 68 | } // namespace bundle_utils 69 | } // namespace hub 70 | 71 | #endif // HUB_BUNDLE_CREATE_BUNDLE_H_ 72 | -------------------------------------------------------------------------------- /hub/commands/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "commands", 3 | srcs = glob( 4 | ["**/*.cc"], 5 | exclude = ["tests/**/*"], 6 | ), 7 | hdrs = glob( 8 | ["**/*.h"], 9 | exclude = ["tests/**/*"], 10 | ), 11 | visibility = ["//visibility:public"], 12 | deps = [ 13 | "//common", 14 | "//common/stats", 15 | "//hub/auth:hmac_provider", 16 | "//hub/bundle:bundle_utils", 17 | "//hub/db", 18 | "@boost//:range", 19 | "@com_github_google_glog//:glog", 20 | "@TangleScope//cppclient:beast", 21 | ], 22 | ) 23 | 24 | cc_test( 25 | name = "tests", 26 | timeout = "long", 27 | srcs = glob([ 28 | "tests/**/*.cc", 29 | "tests/**/*.h", 30 | ]), 31 | deps = [ 32 | ":commands", 33 | "//hub/tests", 34 | "@boost//:range", 35 | "@com_google_googletest//:gtest", 36 | ], 37 | ) 38 | -------------------------------------------------------------------------------- /hub/commands/balance_subscription.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_BALANCE_SUBSCRIPTION_H_ 9 | #define HUB_COMMANDS_BALANCE_SUBSCRIPTION_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "common/commands/command.h" 15 | #include "events.h" 16 | #include "hub/db/helper.h" 17 | 18 | namespace hub { 19 | 20 | namespace cmd { 21 | 22 | typedef struct BalanceSubscriptionRequest { 23 | uint64_t newerThan; 24 | } BalanceSubscriptionRequest; 25 | 26 | /// @param[in] BalanceSubscriptionRequest 27 | /// @param[out] std::vector events 28 | /// Collects records about balance actions to and from user addresses 29 | /// and hub's addresses as well (Depsoits/Withdrawals/Hub address actions) 30 | class BalanceSubscription : public common::Command> { 32 | public: 33 | using Command>::Command; 34 | 35 | static const std::string name() { return "BalanceSubscription"; } 36 | 37 | static std::shared_ptr create() { 38 | return std::shared_ptr( 39 | new BalanceSubscription(std::make_shared())); 40 | } 41 | 42 | virtual std::vector 43 | getAllUsersAccountBalancesSinceTimePoint( 44 | std::chrono::system_clock::time_point lastCheck); 45 | 46 | virtual std::vector 47 | getAllUserAddressesBalancesSinceTimePoint( 48 | std::chrono::system_clock::time_point lastCheck); 49 | 50 | virtual std::vector 51 | getAllHubAddressesBalancesSinceTimePoint( 52 | std::chrono::system_clock::time_point lastCheck); 53 | 54 | common::cmd::Error doProcess( 55 | const BalanceSubscriptionRequest* request, 56 | std::vector* events) noexcept override; 57 | 58 | boost::property_tree::ptree doProcess( 59 | const boost::property_tree::ptree& request) noexcept override; 60 | }; 61 | } // namespace cmd 62 | } // namespace hub 63 | #endif // HUB_COMMANDS_BALANCE_SUBSCRIPTION_H_ 64 | -------------------------------------------------------------------------------- /hub/commands/converter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_PROTO_SQL_CONVERTER_H_ 9 | #define HUB_COMMANDS_PROTO_SQL_CONVERTER_H_ 10 | 11 | #include 12 | 13 | #include "hub/db/types.h" 14 | #include "proto/hub.pb.h" 15 | 16 | #include "events.h" 17 | 18 | namespace hub { 19 | 20 | namespace cmd { 21 | 22 | /// Account balance event 23 | hub::cmd::UserAccountBalanceEventReason userAccountBalanceEventReasonFromSql( 24 | hub::db::UserAccountBalanceReason reason); 25 | 26 | hub::rpc::UserAccountBalanceEventType userAccountBalanceEventReasonToProto( 27 | hub::cmd::UserAccountBalanceEventReason reason); 28 | 29 | std::string userAccountBalanceEventReasonToString( 30 | hub::cmd::UserAccountBalanceEventReason reason); 31 | 32 | /// User address balance event 33 | hub::cmd::UserAddressBalanceEventReason userAddressBalanceEventReasonFromSql( 34 | hub::db::UserAddressBalanceReason reason); 35 | 36 | hub::rpc::UserAddressBalanceReason userAddressBalanceEventReasonToProto( 37 | hub::cmd::UserAddressBalanceEventReason reason); 38 | 39 | std::string userAddressBalanceEventReasonToString( 40 | hub::cmd::UserAddressBalanceEventReason reason); 41 | 42 | /// Hub address balance event 43 | hub::cmd::HubAddressBalanceEventReason hubAddressBalanceReasonFromSql( 44 | hub::db::HubAddressBalanceReason reason); 45 | 46 | hub::rpc::HubAddressBalanceReason hubAddressBalanceReasonToProto( 47 | hub::cmd::HubAddressBalanceEventReason reason); 48 | 49 | std::string hubAddressBalanceReasonToString( 50 | hub::cmd::HubAddressBalanceEventReason reason); 51 | 52 | } // namespace cmd 53 | } // namespace hub 54 | #endif // HUB_COMMANDS_PROTO_SQL_CONVERTER_H_ 55 | -------------------------------------------------------------------------------- /hub/commands/create_user.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/commands/factory.h" 9 | #include "hub/commands/helper.h" 10 | #include "hub/db/helper.h" 11 | 12 | #include "hub/commands/create_user.h" 13 | 14 | namespace hub { 15 | namespace cmd { 16 | 17 | static CommandFactoryRegistrator registrator; 18 | 19 | boost::property_tree::ptree CreateUser::doProcess( 20 | const boost::property_tree::ptree& request) noexcept { 21 | boost::property_tree::ptree tree; 22 | CreateUserRequest req; 23 | CreateUserReply rep; 24 | auto maybeUserId = request.get_optional("userId"); 25 | if (!maybeUserId) { 26 | tree.add("error", 27 | common::cmd::getErrorString(common::cmd::MISSING_ARGUMENT)); 28 | return tree; 29 | } 30 | req.userId = maybeUserId.value(); 31 | auto status = doProcess(&req, &rep); 32 | 33 | if (status != common::cmd::OK) { 34 | tree.add("error", common::cmd::getErrorString(status)); 35 | } 36 | 37 | return tree; 38 | } 39 | 40 | common::cmd::Error CreateUser::doProcess(const CreateUserRequest* request, 41 | CreateUserReply* response) noexcept { 42 | auto& connection = db::DBManager::get().connection(); 43 | 44 | auto transaction = connection.transaction(); 45 | 46 | try { 47 | connection.createUser(request->userId); 48 | transaction->commit(); 49 | } catch (const sqlpp::exception& ex) { 50 | LOG(ERROR) << session() << " Commit failed: " << ex.what(); 51 | 52 | try { 53 | transaction->rollback(); 54 | } catch (const sqlpp::exception& ex) { 55 | LOG(ERROR) << session() << " Rollback failed: " << ex.what(); 56 | } 57 | 58 | return common::cmd::USER_EXISTS; 59 | } 60 | 61 | LOG(INFO) << session() << " Created user: " << request->userId; 62 | 63 | return common::cmd::OK; 64 | } 65 | 66 | } // namespace cmd 67 | 68 | } // namespace hub 69 | -------------------------------------------------------------------------------- /hub/commands/create_user.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_CREATE_USER_H_ 9 | #define HUB_COMMANDS_CREATE_USER_H_ 10 | 11 | #include "common/commands/command.h" 12 | 13 | #include 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | typedef struct CreateUserRequest { 19 | std::string userId; 20 | 21 | } CreateUserRequest; 22 | 23 | typedef struct CreateUserReply { 24 | std::string userId; 25 | 26 | } CreateUserReply; 27 | 28 | /// Creates a new user with a specific id. 29 | /// @param[in] CreateUserRequest 30 | /// @param[in] CreateUserReply 31 | class CreateUser : public common::Command { 32 | public: 33 | using Command::Command; 34 | 35 | static std::shared_ptr create() { 36 | return std::shared_ptr( 37 | new CreateUser(std::make_shared())); 38 | } 39 | 40 | static const std::string name() { return "CreateUser"; } 41 | 42 | common::cmd::Error doProcess(const CreateUserRequest* request, 43 | CreateUserReply* response) noexcept override; 44 | 45 | boost::property_tree::ptree doProcess( 46 | const boost::property_tree::ptree& request) noexcept override; 47 | }; 48 | } // namespace cmd 49 | } // namespace hub 50 | 51 | #endif // HUB_COMMANDS_CREATE_USER_H_ 52 | -------------------------------------------------------------------------------- /hub/commands/factory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_FACTORY_H_ 9 | #define HUB_COMMANDS_FACTORY_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "common/commands/command.h" 16 | #include "cppclient/api.h" 17 | 18 | namespace hub { 19 | 20 | namespace cmd { 21 | 22 | typedef std::shared_ptr (*CreateCommandFn)(void); 23 | 24 | class CommandFactory { 25 | public: 26 | static std::shared_ptr create( 27 | std::string_view name, std::shared_ptr api) { 28 | std::shared_ptr cmd; 29 | try { 30 | auto creator = get()->_factoryMap.at(name.data()); 31 | cmd = creator(); 32 | if (cmd->needApi()) { 33 | cmd->setApi(api); 34 | } 35 | } catch (const std::out_of_range &e) { 36 | LOG(ERROR) << name << " is an unknown command\n"; 37 | } 38 | 39 | return cmd; 40 | } 41 | CommandFactory(const CommandFactory &) = delete; 42 | CommandFactory &operator=(const CommandFactory &) = delete; 43 | 44 | ~CommandFactory() { _factoryMap.clear(); } 45 | 46 | static CommandFactory *get() { 47 | static CommandFactory _instance; 48 | return &_instance; 49 | } 50 | 51 | void registerCreator(const std::string name, 52 | CreateCommandFn commandCreateFn) { 53 | _factoryMap.emplace(name, commandCreateFn); 54 | }; 55 | 56 | private: 57 | CommandFactory(){}; 58 | typedef std::map FactoryMap; 59 | FactoryMap _factoryMap; 60 | }; 61 | 62 | template 63 | class CommandFactoryRegistrator { 64 | public: 65 | CommandFactoryRegistrator() { 66 | CommandFactory::get()->registerCreator(Cmd::name(), Cmd::create); 67 | } 68 | CommandFactoryRegistrator(const CommandFactory &) = delete; 69 | CommandFactoryRegistrator &operator=(const CommandFactory &) = delete; 70 | }; 71 | } // namespace cmd 72 | } // namespace hub 73 | 74 | #endif // HUB_COMMANDS_FACTORY_H_ 75 | -------------------------------------------------------------------------------- /hub/commands/get_address_info.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include "common/crypto/manager.h" 11 | #include "common/crypto/types.h" 12 | #include "hub/commands/factory.h" 13 | #include "hub/commands/helper.h" 14 | #include "hub/db/helper.h" 15 | 16 | #include "hub/commands/get_address_info.h" 17 | 18 | namespace hub { 19 | namespace cmd { 20 | 21 | static CommandFactoryRegistrator registrator; 22 | 23 | boost::property_tree::ptree GetAddressInfo::doProcess( 24 | const boost::property_tree::ptree& request) noexcept { 25 | boost::property_tree::ptree tree; 26 | GetAddressInfoRequest req; 27 | GetAddressInfoReply rep; 28 | 29 | auto maybeAddress = request.get_optional("address"); 30 | if (!maybeAddress) { 31 | tree.add("error", 32 | common::cmd::getErrorString(common::cmd::MISSING_ARGUMENT)); 33 | return tree; 34 | } 35 | req.address = maybeAddress.value(); 36 | auto status = doProcess(&req, &rep); 37 | 38 | if (status != common::cmd::OK) { 39 | tree.add("error", common::cmd::getErrorString(status)); 40 | } else { 41 | tree.add("userId", rep.userId); 42 | } 43 | 44 | return tree; 45 | } 46 | 47 | common::cmd::Error GetAddressInfo::doProcess( 48 | const GetAddressInfoRequest* request, 49 | GetAddressInfoReply* response) noexcept { 50 | auto& connection = db::DBManager::get().connection(); 51 | 52 | try { 53 | common::crypto::Address address(request->address); 54 | 55 | auto addressInfo = connection.getAddressInfo(address); 56 | 57 | if (addressInfo) { 58 | response->userId = std::move(addressInfo->userId); 59 | return common::cmd::OK; 60 | } 61 | } catch (const std::exception& ex) { 62 | return common::cmd::UNKNOWN_ERROR; 63 | } 64 | 65 | return common::cmd::UNKNOWN_ADDRESS; 66 | } 67 | 68 | } // namespace cmd 69 | } // namespace hub 70 | -------------------------------------------------------------------------------- /hub/commands/get_address_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_ADDRESS_INFO_H_ 9 | #define HUB_COMMANDS_GET_ADDRESS_INFO_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | /// Gets information on an address 19 | /// @param[in] GetAddressInfoRequest 20 | /// @param[in] GetAddressInfoReply 21 | 22 | typedef struct GetAddressInfoRequest { 23 | std::string address; 24 | } GetAddressInfoRequest; 25 | 26 | typedef struct GetAddressInfoReply { 27 | std::string userId; 28 | } GetAddressInfoReply; 29 | 30 | class GetAddressInfo 31 | : public common::Command { 32 | public: 33 | using Command::Command; 34 | 35 | static std::shared_ptr create() { 36 | return std::shared_ptr( 37 | new GetAddressInfo(std::make_shared())); 38 | } 39 | 40 | static const std::string name() { return "GetAddressInfo"; } 41 | 42 | common::cmd::Error doProcess(const GetAddressInfoRequest *request, 43 | GetAddressInfoReply *response) noexcept override; 44 | 45 | boost::property_tree::ptree doProcess( 46 | const boost::property_tree::ptree &request) noexcept override; 47 | }; 48 | } // namespace cmd 49 | } // namespace hub 50 | 51 | #endif // HUB_COMMANDS_GET_ADDRESS_INFO_H_ 52 | -------------------------------------------------------------------------------- /hub/commands/get_balance.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include "hub/commands/factory.h" 11 | #include "hub/commands/helper.h" 12 | #include "hub/db/helper.h" 13 | 14 | #include "hub/commands/get_balance.h" 15 | 16 | namespace hub { 17 | namespace cmd { 18 | 19 | static CommandFactoryRegistrator registrator; 20 | 21 | boost::property_tree::ptree GetBalance::doProcess( 22 | const boost::property_tree::ptree& request) noexcept { 23 | boost::property_tree::ptree tree; 24 | GetBalanceRequest req; 25 | GetBalanceReply rep; 26 | 27 | auto maybeUserId = request.get_optional("userId"); 28 | if (!maybeUserId) { 29 | tree.add("error", 30 | common::cmd::getErrorString(common::cmd::MISSING_ARGUMENT)); 31 | return tree; 32 | } 33 | 34 | req.userId = maybeUserId.value(); 35 | 36 | auto status = doProcess(&req, &rep); 37 | 38 | if (status != common::cmd::OK) { 39 | tree.add("error", common::cmd::getErrorString(status)); 40 | } else { 41 | tree.add("available", rep.available); 42 | } 43 | return tree; 44 | } 45 | 46 | common::cmd::Error GetBalance::doProcess(const GetBalanceRequest* request, 47 | GetBalanceReply* response) noexcept { 48 | auto& connection = db::DBManager::get().connection(); 49 | uint64_t userId; 50 | 51 | // Get userId for identifier 52 | { 53 | auto maybeUserId = connection.userIdFromIdentifier(request->userId); 54 | if (!maybeUserId) { 55 | return common::cmd::USER_DOES_NOT_EXIST; 56 | } 57 | 58 | userId = maybeUserId.value(); 59 | } 60 | 61 | // Summarise all amounts for user_account_balance changes 62 | auto amount = connection.availableBalanceForUser(userId); 63 | response->available = amount; 64 | 65 | return common::cmd::OK; 66 | } 67 | 68 | } // namespace cmd 69 | 70 | } // namespace hub 71 | -------------------------------------------------------------------------------- /hub/commands/get_balance.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_BALANCE_H_ 9 | #define HUB_COMMANDS_GET_BALANCE_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | 17 | namespace cmd { 18 | 19 | typedef struct GetBalanceRequest { 20 | std::string userId; 21 | } GetBalanceRequest; 22 | 23 | typedef struct GetBalanceReply { 24 | uint64_t available; 25 | } GetBalanceReply; 26 | 27 | /// Gets the current balance for a user with a specific id. 28 | /// @param[in] GetBalanceRequest 29 | /// @param[in] GetBalanceReply 30 | class GetBalance : public common::Command { 31 | public: 32 | using Command::Command; 33 | 34 | static std::shared_ptr create() { 35 | return std::shared_ptr( 36 | new GetBalance(std::make_shared())); 37 | } 38 | 39 | static const std::string name() { return "GetBalance"; } 40 | 41 | common::cmd::Error doProcess(const GetBalanceRequest* request, 42 | GetBalanceReply* response) noexcept override; 43 | 44 | boost::property_tree::ptree doProcess( 45 | const boost::property_tree::ptree& request) noexcept override; 46 | }; 47 | } // namespace cmd 48 | } // namespace hub 49 | 50 | #endif // HUB_COMMANDS_GET_BALANCE_H_ 51 | -------------------------------------------------------------------------------- /hub/commands/get_deposit_address.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_DEPOSIT_ADDRESS_H_ 9 | #define HUB_COMMANDS_GET_DEPOSIT_ADDRESS_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | typedef struct GetDepositAddressRequest { 19 | GetDepositAddressRequest() : includeChecksum(false) {} 20 | std::string userId; 21 | bool includeChecksum; 22 | } GetDepositAddressRequest; 23 | 24 | typedef struct GetDepositAddressReply { 25 | std::string address; 26 | } GetDepositAddressReply; 27 | 28 | class GetDepositAddress 29 | : public common::Command { 30 | public: 31 | using Command::Command; 32 | 33 | static std::shared_ptr create() { 34 | return std::shared_ptr( 35 | new GetDepositAddress(std::make_shared())); 36 | } 37 | 38 | static const std::string name() { return "GetDepositAddress"; } 39 | 40 | common::cmd::Error doProcess( 41 | const GetDepositAddressRequest* request, 42 | GetDepositAddressReply* response) noexcept override; 43 | 44 | boost::property_tree::ptree doProcess( 45 | const boost::property_tree::ptree& request) noexcept override; 46 | }; 47 | } // namespace cmd 48 | } // namespace hub 49 | 50 | #endif // HUB_COMMANDS_GET_DEPOSIT_ADDRESS_H_ 51 | -------------------------------------------------------------------------------- /hub/commands/get_seed_for_address.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_SEED_FOR_ADDRESS_H_ 9 | #define HUB_COMMANDS_GET_SEED_FOR_ADDRESS_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | typedef struct GetSeedForAddressRequest { 19 | std::string userId; 20 | std::string address; 21 | } GetSeedForAddressRequest; 22 | 23 | typedef struct GetSeedForAddressReply { 24 | std::string seed; 25 | } GetSeedForAddressReply; 26 | 27 | class GetSeedForAddress 28 | : public common::Command { 29 | public: 30 | using Command::Command; 31 | 32 | static std::shared_ptr create() { 33 | return std::shared_ptr( 34 | new GetSeedForAddress(std::make_shared())); 35 | } 36 | 37 | static const std::string name() { return "GetSeedForAddress"; } 38 | 39 | common::cmd::Error doProcess( 40 | const GetSeedForAddressRequest* request, 41 | GetSeedForAddressReply* response) noexcept override; 42 | 43 | boost::property_tree::ptree doProcess( 44 | const boost::property_tree::ptree& request) noexcept override; 45 | }; 46 | } // namespace cmd 47 | } // namespace hub 48 | 49 | #endif // HUB_COMMANDS_GET_SEED_FOR_ADDRESS_H_ 50 | -------------------------------------------------------------------------------- /hub/commands/get_seed_for_uuid.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include "common/crypto/manager.h" 11 | #include "hub/commands/factory.h" 12 | #include "hub/commands/helper.h" 13 | 14 | #include "hub/commands/get_seed_for_uuid.h" 15 | 16 | namespace hub { 17 | namespace cmd { 18 | 19 | static CommandFactoryRegistrator registrator; 20 | 21 | boost::property_tree::ptree GetSeedForUUID::doProcess( 22 | const boost::property_tree::ptree& request) noexcept { 23 | boost::property_tree::ptree tree; 24 | GetSeedForUUIDRequest req; 25 | GetSeedForUUIDReply rep; 26 | 27 | auto maybeUUID = request.get_optional("uuid"); 28 | if (!maybeUUID) { 29 | tree.add("error", 30 | common::cmd::getErrorString(common::cmd::MISSING_ARGUMENT)); 31 | return tree; 32 | } 33 | 34 | req.uuid = maybeUUID.value(); 35 | 36 | auto status = doProcess(&req, &rep); 37 | 38 | if (status != common::cmd::OK) { 39 | tree.add("error", common::cmd::getErrorString(status)); 40 | } else { 41 | tree.add("seed", rep.seed); 42 | } 43 | return tree; 44 | } 45 | 46 | common::cmd::Error GetSeedForUUID::doProcess( 47 | const GetSeedForUUIDRequest* request, 48 | GetSeedForUUIDReply* response) noexcept { 49 | // Get seed by the uuid 50 | response->seed = 51 | common::crypto::CryptoManager::get().provider().getSeedFromUUID( 52 | common::crypto::UUID(request->uuid)); 53 | 54 | return common::cmd::OK; 55 | } 56 | } // namespace cmd 57 | } // namespace hub 58 | -------------------------------------------------------------------------------- /hub/commands/get_seed_for_uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_SEED_FOR_UUID_H_ 9 | #define HUB_COMMANDS_GET_SEED_FOR_UUID_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | typedef struct GetSeedForUUIDRequest { 19 | std::string uuid; 20 | } GetSeedForUUIDRequest; 21 | 22 | typedef struct GetSeedForUUIDReply { 23 | std::string seed; 24 | } GetSeedForUUIDReply; 25 | 26 | class GetSeedForUUID 27 | : public common::Command { 28 | public: 29 | using Command::Command; 30 | 31 | static std::shared_ptr create() { 32 | return std::shared_ptr( 33 | new GetSeedForUUID(std::make_shared())); 34 | } 35 | 36 | static const std::string name() { return "GetSeedForUUID"; } 37 | 38 | common::cmd::Error doProcess(const GetSeedForUUIDRequest* request, 39 | GetSeedForUUIDReply* response) noexcept override; 40 | 41 | boost::property_tree::ptree doProcess( 42 | const boost::property_tree::ptree& request) noexcept override; 43 | }; 44 | } // namespace cmd 45 | } // namespace hub 46 | 47 | #endif // HUB_COMMANDS_GET_SEED_FOR_UUID_H_ 48 | -------------------------------------------------------------------------------- /hub/commands/get_stats.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include "hub/commands/factory.h" 11 | #include "hub/commands/helper.h" 12 | #include "hub/db/helper.h" 13 | 14 | #include "hub/commands/get_stats.h" 15 | 16 | namespace hub { 17 | namespace cmd { 18 | 19 | static CommandFactoryRegistrator registrator; 20 | 21 | boost::property_tree::ptree GetStats::doProcess( 22 | const boost::property_tree::ptree& request) noexcept { 23 | boost::property_tree::ptree tree; 24 | GetStatsRequest req; 25 | GetStatsReply rep; 26 | auto status = doProcess(&req, &rep); 27 | 28 | if (status != common::cmd::OK) { 29 | tree.add("error", common::cmd::getErrorString(status)); 30 | } else { 31 | tree.add("totalBalance", rep.totalBalance); 32 | } 33 | return tree; 34 | } 35 | 36 | common::cmd::Error GetStats::doProcess(const GetStatsRequest* request, 37 | GetStatsReply* response) noexcept { 38 | auto& connection = db::DBManager::get().connection(); 39 | 40 | response->totalBalance = connection.getTotalBalance(); 41 | 42 | return common::cmd::OK; 43 | } 44 | 45 | } // namespace cmd 46 | 47 | } // namespace hub 48 | -------------------------------------------------------------------------------- /hub/commands/get_stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_STATS_H_ 9 | #define HUB_COMMANDS_GET_STATS_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | typedef struct GetStatsRequest { 19 | } GetStatsRequest; 20 | 21 | typedef struct GetStatsReply { 22 | uint64_t totalBalance; 23 | } GetStatsReply; 24 | 25 | /// Gets statistics about the Hub's current state 26 | /// @param[in] GetStatsRequest 27 | /// @param[in] GetStatsReply 28 | class GetStats : public common::Command { 29 | public: 30 | using Command::Command; 31 | 32 | static std::shared_ptr create() { 33 | return std::shared_ptr( 34 | new GetStats(std::make_shared())); 35 | } 36 | 37 | static const std::string name() { return "GetStats"; } 38 | 39 | common::cmd::Error doProcess(const GetStatsRequest* request, 40 | GetStatsReply* response) noexcept override; 41 | 42 | boost::property_tree::ptree doProcess( 43 | const boost::property_tree::ptree& request) noexcept override; 44 | }; 45 | } // namespace cmd 46 | } // namespace hub 47 | #endif // HUB_COMMANDS_GET_STATS_H_ 48 | -------------------------------------------------------------------------------- /hub/commands/get_user_history.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_GET_USER_HISTORY_H_ 9 | #define HUB_COMMANDS_GET_USER_HISTORY_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "common/commands/command.h" 15 | #include "hub/commands/events.h" 16 | 17 | namespace hub { 18 | namespace cmd { 19 | 20 | /// Gets the history of transactions for a user. 21 | /// @param[in] GetUserHistoryRequest 22 | /// @param[in] GetUserHistoryReply 23 | 24 | typedef struct GetUserHistoryRequest { 25 | std::string userId; 26 | uint64_t newerThan; 27 | } GetUserHistoryRequest; 28 | 29 | typedef struct GetUserHistoryReply { 30 | std::vector events; 31 | } GetUserHistoryReply; 32 | 33 | class GetUserHistory 34 | : public common::Command { 35 | public: 36 | using Command::Command; 37 | 38 | static std::shared_ptr create() { 39 | return std::shared_ptr( 40 | new GetUserHistory(std::make_shared())); 41 | } 42 | 43 | static const std::string name() { return "GetUserHistory"; } 44 | 45 | common::cmd::Error doProcess(const GetUserHistoryRequest* request, 46 | GetUserHistoryReply* response) noexcept override; 47 | 48 | boost::property_tree::ptree doProcess( 49 | const boost::property_tree::ptree& request) noexcept override; 50 | }; 51 | } // namespace cmd 52 | } // namespace hub 53 | #endif // HUB_COMMANDS_GET_USER_HISTORY_H_ 54 | -------------------------------------------------------------------------------- /hub/commands/helper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "hub/commands/helper.h" 12 | 13 | namespace hub { 14 | namespace cmd { 15 | std::string errorToString(const hub::rpc::ErrorCode& e) { 16 | std::ostringstream ss; 17 | hub::rpc::Error error; 18 | 19 | error.set_code(e); 20 | error.SerializeToOstream(&ss); 21 | 22 | return ss.str(); 23 | } 24 | 25 | bool isAddressValid(std::string_view sv) { 26 | bool is_valid = true; 27 | switch (sv[80]) { 28 | case '9': 29 | case 'A': 30 | case 'B': 31 | case 'C': 32 | case 'D': 33 | case 'W': 34 | case 'X': 35 | case 'Y': 36 | case 'Z': 37 | break; 38 | default: 39 | is_valid = false; 40 | } 41 | return is_valid; 42 | } 43 | 44 | } // namespace cmd 45 | } // namespace hub 46 | -------------------------------------------------------------------------------- /hub/commands/helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_HELPER_H_ 9 | #define HUB_COMMANDS_HELPER_H_ 10 | 11 | #include 12 | 13 | #include "proto/hub.pb.h" 14 | 15 | namespace hub { 16 | 17 | namespace cmd { 18 | std::string errorToString(const hub::rpc::ErrorCode& e); 19 | 20 | bool isAddressValid(std::string_view sv); 21 | } // namespace cmd 22 | } // namespace hub 23 | 24 | #endif // HUB_COMMANDS_HELPER_H_ 25 | -------------------------------------------------------------------------------- /hub/commands/process_transfer_batch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_PROCESS_TRANSFER_BATCH_H_ 9 | #define HUB_COMMANDS_PROCESS_TRANSFER_BATCH_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "common/commands/command.h" 16 | 17 | namespace hub { 18 | 19 | namespace cmd { 20 | 21 | typedef struct UserTransfer { 22 | std::string userId; 23 | int64_t amount; 24 | } UserTransfer; 25 | 26 | typedef struct ProcessTransferBatchRequest { 27 | std::vector transfers; 28 | } ProcessTransferBatchRequest; 29 | typedef struct ProcessTransferBatchReply { 30 | } ProcessTransferBatchReply; 31 | 32 | /// Invokes the processing of a batch of transfers. 33 | /// @param[in] ProcessTransferBatchRequest 34 | /// @param[in] ProcessTransferBatchReply 35 | 36 | class ProcessTransferBatch : public common::Command { 38 | public: 39 | using Command::Command; 41 | 42 | static std::shared_ptr create() { 43 | return std::shared_ptr( 44 | new ProcessTransferBatch(std::make_shared())); 45 | } 46 | 47 | static const std::string name() { return "ProcessTransferBatch"; } 48 | 49 | common::cmd::Error doProcess( 50 | const ProcessTransferBatchRequest* request, 51 | ProcessTransferBatchReply* response) noexcept override; 52 | 53 | boost::property_tree::ptree doProcess( 54 | const boost::property_tree::ptree& request) noexcept override; 55 | 56 | private: 57 | /// Checks the validity of a batch transfer. For a batch transfer to be valid, 58 | /// it must conform to the following criteria: 59 | /// - There must be no zero transfers 60 | /// - The sum of all transfers in the batch must amount to zero 61 | /// - Users must have sufficient funds available 62 | common::cmd::Error validateTransfers( 63 | const ProcessTransferBatchRequest* request, 64 | const std::map& identifierToId) noexcept; 65 | }; 66 | } // namespace cmd 67 | } // namespace hub 68 | 69 | #endif // HUB_COMMANDS_PROCESS_TRANSFER_BATCH_H_ 70 | -------------------------------------------------------------------------------- /hub/commands/recover_funds.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_RECOVER_FUNDS_H_ 9 | #define HUB_COMMANDS_RECOVER_FUNDS_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | #include "cppclient/api.h" 15 | 16 | DECLARE_bool(RecoverFunds_enabled); 17 | 18 | namespace hub { 19 | namespace cmd { 20 | 21 | typedef struct RecoverFundsRequest { 22 | std::string userId; 23 | std::string address; 24 | std::string payoutAddress; 25 | bool validateChecksum; 26 | } RecoverFundsRequest; 27 | typedef struct RecoverFundsReply { 28 | } RecoverFundsReply; 29 | 30 | /// Recover funds from an already spent address into an output address 31 | /// @param[in] RecoverFundsRequest 32 | /// @param[in] RecoverFundsReply 33 | class RecoverFunds 34 | : public common::Command { 35 | public: 36 | using Command::Command; 37 | 38 | static std::shared_ptr create() { 39 | return std::shared_ptr( 40 | new RecoverFunds(std::make_shared())); 41 | } 42 | 43 | explicit RecoverFunds(std::shared_ptr session, 44 | std::shared_ptr api) 45 | : Command(std::move(session)), _api(std::move(api)) {} 46 | 47 | static const std::string name() { return "RecoverFunds"; } 48 | 49 | common::cmd::Error doProcess(const RecoverFundsRequest* request, 50 | RecoverFundsReply* response) noexcept override; 51 | 52 | boost::property_tree::ptree doProcess( 53 | const boost::property_tree::ptree& request) noexcept override; 54 | 55 | virtual bool needApi() const override { return true; } 56 | 57 | virtual void setApi(std::shared_ptr api) { _api = api; } 58 | 59 | private: 60 | std::shared_ptr _api; 61 | }; 62 | } // namespace cmd 63 | } // namespace hub 64 | 65 | #endif // HUB_COMMANDS_RECOVER_FUNDS_H_ 66 | -------------------------------------------------------------------------------- /hub/commands/sign_bundle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_SIGN_BUNDLE_H_ 9 | #define HUB_COMMANDS_SIGN_BUNDLE_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | DECLARE_bool(SignBundle_enabled); 16 | 17 | namespace hub { 18 | 19 | namespace cmd { 20 | 21 | typedef struct SignBundleRequest { 22 | bool validateChecksum; 23 | std::string address; 24 | std::string authenticationToken; 25 | std::string bundleHash; 26 | } SignBundleRequest; 27 | typedef struct SignBundleReply { 28 | std::string signature; 29 | } SignBundleReply; 30 | 31 | /// Gets information on an address 32 | /// @param[in] SignBundleRequest 33 | /// @param[in] SignBundleReply 34 | class SignBundle : public common::Command { 35 | public: 36 | using Command::Command; 37 | 38 | static std::shared_ptr create() { 39 | return std::shared_ptr( 40 | new SignBundle(std::make_shared())); 41 | } 42 | 43 | static const std::string name() { return "SignBundle"; } 44 | 45 | common::cmd::Error doProcess(const SignBundleRequest* request, 46 | SignBundleReply* response) noexcept override; 47 | 48 | boost::property_tree::ptree doProcess( 49 | const boost::property_tree::ptree& request) noexcept override; 50 | }; 51 | } // namespace cmd 52 | } // namespace hub 53 | 54 | #endif // HUB_COMMANDS_SIGN_BUNDLE_H_ 55 | -------------------------------------------------------------------------------- /hub/commands/sweep_detail.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "common/converter.h" 13 | #include "common/crypto/types.h" 14 | #include "hub/commands/factory.h" 15 | #include "hub/commands/helper.h" 16 | #include "hub/db/helper.h" 17 | 18 | #include "hub/commands/sweep_detail.h" 19 | 20 | namespace hub { 21 | namespace cmd { 22 | 23 | static CommandFactoryRegistrator registrator; 24 | 25 | boost::property_tree::ptree SweepDetail::doProcess( 26 | const boost::property_tree::ptree& request) noexcept { 27 | boost::property_tree::ptree tree; 28 | SweepDetailRequest req; 29 | SweepDetailReply rep; 30 | 31 | auto maybeBundleHash = request.get_optional("bundleHash"); 32 | if (maybeBundleHash) { 33 | req.bundleHash = maybeBundleHash.value(); 34 | 35 | auto status = doProcess(&req, &rep); 36 | 37 | if (status != common::cmd::OK) { 38 | tree.add("error", common::cmd::getErrorString(status)); 39 | } else { 40 | tree.add("confirmed", common::boolToString(rep.confirmed)); 41 | 42 | for (auto txTrytes : rep.trytes) { 43 | tree.add("trytes", txTrytes); 44 | } 45 | 46 | for (auto tailHash : rep.tailHashes) { 47 | tree.add("tailHash", tailHash); 48 | } 49 | } 50 | } else { 51 | tree.add("error", 52 | common::cmd::getErrorString(common::cmd::MISSING_ARGUMENT)); 53 | } 54 | 55 | return tree; 56 | } 57 | 58 | common::cmd::Error SweepDetail::doProcess(const SweepDetailRequest* request, 59 | SweepDetailReply* response) noexcept { 60 | auto& connection = db::DBManager::get().connection(); 61 | 62 | nonstd::optional maybeDetail; 63 | 64 | try { 65 | common::crypto::Hash bundleHash(request->bundleHash); 66 | maybeDetail = connection.getSweepDetailByBundleHash(bundleHash); 67 | } catch (const std::exception& ex) { 68 | // ignore, hash parsing probably failed. 69 | } 70 | 71 | if (!maybeDetail) { 72 | return common::cmd::CANCELLED; 73 | } 74 | 75 | response->confirmed = maybeDetail->confirmed; 76 | auto trytesVec = std::move(maybeDetail->trytes); 77 | std::for_each(trytesVec.begin(), trytesVec.end(), [&](std::string& trytes) { 78 | response->trytes.emplace_back(std::move(trytes)); 79 | }); 80 | 81 | auto tailsVec = std::move(maybeDetail->tails); 82 | std::for_each(tailsVec.begin(), tailsVec.end(), 83 | [&](common::crypto::Hash& tail) { 84 | response->tailHashes.emplace_back(std::move(tail.str())); 85 | }); 86 | 87 | return common::cmd::OK; 88 | } 89 | 90 | } // namespace cmd 91 | } // namespace hub 92 | -------------------------------------------------------------------------------- /hub/commands/sweep_detail.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_SWEEP_DETAIL_H_ 9 | #define HUB_COMMANDS_SWEEP_DETAIL_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | 17 | namespace cmd { 18 | 19 | typedef struct SweepDetailRequest { 20 | std::string bundleHash; 21 | } SweepDetailRequest; 22 | typedef struct SweepDetailReply { 23 | bool confirmed; 24 | std::vector trytes; 25 | std::vector tailHashes; 26 | 27 | } SweepDetailReply; 28 | 29 | /// Gets the history of transactions for a user. 30 | /// @param[in] SweepInfoRequest 31 | /// @param[in] SweepEvent 32 | class SweepDetail 33 | : public common::Command { 34 | public: 35 | using Command::Command; 36 | 37 | static std::shared_ptr create() { 38 | return std::shared_ptr( 39 | new SweepDetail(std::make_shared())); 40 | } 41 | 42 | static const std::string name() { return "SweepDetail"; } 43 | 44 | common::cmd::Error doProcess(const SweepDetailRequest* request, 45 | SweepDetailReply* response) noexcept override; 46 | 47 | boost::property_tree::ptree doProcess( 48 | const boost::property_tree::ptree& request) noexcept override; 49 | }; 50 | } // namespace cmd 51 | } // namespace hub 52 | #endif // HUB_COMMANDS_SWEEP_DETAIL_H_ 53 | -------------------------------------------------------------------------------- /hub/commands/sweep_info.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_SWEEP_INFO_H_ 9 | #define HUB_COMMANDS_SWEEP_INFO_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | #include "events.h" 15 | 16 | namespace hub { 17 | 18 | namespace cmd { 19 | 20 | typedef struct SweepInfoRequest { 21 | bool requestByUuid; 22 | std::string bundleHash; 23 | std::string uuid; 24 | } SweepInfoRequest; 25 | 26 | /// Gets the history of transactions for a user. 27 | /// @param[in] SweepInfoRequest 28 | /// @param[in] SweepEvent 29 | class SweepInfo : public common::Command { 30 | public: 31 | using Command::Command; 32 | 33 | static std::shared_ptr create() { 34 | return std::shared_ptr( 35 | new SweepInfo(std::make_shared())); 36 | } 37 | 38 | static const std::string name() { return "SweepInfo"; } 39 | 40 | common::cmd::Error doProcess(const SweepInfoRequest* request, 41 | SweepEvent* response) noexcept override; 42 | 43 | boost::property_tree::ptree doProcess( 44 | const boost::property_tree::ptree& request) noexcept override; 45 | }; 46 | } // namespace cmd 47 | } // namespace hub 48 | #endif // HUB_COMMANDS_SWEEP_INFO_H_ 49 | -------------------------------------------------------------------------------- /hub/commands/sweep_subscription.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | #include 5 | 6 | #include "common/converter.h" 7 | #include "hub/commands/converter.h" 8 | #include "hub/commands/factory.h" 9 | #include "hub/commands/helper.h" 10 | #include "hub/db/helper.h" 11 | 12 | #include "hub/commands/sweep_subscription.h" 13 | 14 | namespace hub { 15 | namespace cmd { 16 | 17 | static CommandFactoryRegistrator registrator; 18 | 19 | boost::property_tree::ptree SweepSubscription::doProcess( 20 | const boost::property_tree::ptree& request) noexcept { 21 | boost::property_tree::ptree tree; 22 | SweepSubscriptionRequest req; 23 | std::vector rep; 24 | 25 | auto maybeNewerThan = request.get_optional("newerThan"); 26 | if (maybeNewerThan) { 27 | std::istringstream iss(maybeNewerThan.value()); 28 | iss >> req.newerThan; 29 | } 30 | 31 | auto status = doProcess(&req, &rep); 32 | 33 | if (status != common::cmd::OK) { 34 | tree.add("error", common::cmd::getErrorString(status)); 35 | } else { 36 | int i = 0; 37 | for (auto event : rep) { 38 | auto eventId = "event_" + std::to_string(i++); 39 | tree.add(eventId, ""); 40 | tree.put(eventId + ".bundleHash", event.bundleHash); 41 | tree.put(eventId + ".timestamp", event.timestamp); 42 | 43 | for (auto uuid : event.uuids) { 44 | tree.add(eventId + ".withdrawalUuid", uuid); 45 | } 46 | } 47 | } 48 | 49 | return tree; 50 | } 51 | 52 | common::cmd::Error SweepSubscription::doProcess( 53 | const SweepSubscriptionRequest* request, 54 | std::vector* events) noexcept { 55 | std::chrono::milliseconds dur(request->newerThan); 56 | std::chrono::time_point newerThan(dur); 57 | 58 | auto sweeps = getSweeps(newerThan); 59 | for (auto& s : sweeps) { 60 | SweepEvent event; 61 | event.bundleHash = std::move(s.bundleHash); 62 | event.timestamp = common::timepointToUint64(s.timestamp); 63 | auto& uuids = s.withdrawalUUIDs; 64 | 65 | std::for_each(uuids.begin(), uuids.end(), [&](std::string& uuid) { 66 | event.uuids.emplace_back(std::move(uuid)); 67 | }); 68 | 69 | events->emplace_back(std::move(event)); 70 | } 71 | return common::cmd::OK; 72 | } 73 | 74 | std::vector SweepSubscription::getSweeps( 75 | std::chrono::system_clock::time_point newerThan) { 76 | return db::DBManager::get().connection().getSweeps(newerThan); 77 | } 78 | 79 | } // namespace cmd 80 | } // namespace hub 81 | -------------------------------------------------------------------------------- /hub/commands/sweep_subscription.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #ifndef HUB_COMMANDS_SWEEP_SUBSCRIPTION_H_ 4 | #define HUB_COMMANDS_SWEEP_SUBSCRIPTION_H_ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "common/commands/command.h" 11 | #include "events.h" 12 | 13 | namespace hub { 14 | 15 | namespace cmd { 16 | 17 | typedef struct SweepSubscriptionRequest { 18 | uint64_t newerThan; 19 | } SweepSubscriptionRequest; 20 | 21 | class SweepSubscription : public common::Command> { 23 | public: 24 | using Command>::Command; 25 | 26 | static std::shared_ptr create() { 27 | return std::shared_ptr( 28 | new SweepSubscription(std::make_shared())); 29 | } 30 | 31 | common::cmd::Error doProcess( 32 | const SweepSubscriptionRequest* request, 33 | std::vector* events) noexcept override; 34 | 35 | boost::property_tree::ptree doProcess( 36 | const boost::property_tree::ptree& request) noexcept override; 37 | 38 | static const std::string name() { return "SweepSubscription"; } 39 | 40 | virtual std::vector getSweeps( 41 | std::chrono::system_clock::time_point lastCheck); 42 | }; 43 | } // namespace cmd 44 | } // namespace hub 45 | #endif // HUB_COMMANDS_SWEEP_SUBSCRIPTION_H_ 46 | -------------------------------------------------------------------------------- /hub/commands/tests/helper.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include "hub/commands/tests/helper.h" 4 | 5 | namespace hub { 6 | 7 | namespace tests { 8 | 9 | std::map createZigZagTransfer( 10 | std::vector& users, cmd::ProcessTransferBatchRequest& req, 11 | int64_t absAmount) { 12 | std::map idsToTransAmount; 13 | for (uint32_t i = 0; i < users.size(); ++i) { 14 | int64_t mul = (i % 2) ? 1 : -1; 15 | req.transfers.emplace_back( 16 | cmd::UserTransfer{userId : users[i], amount : mul * absAmount}); 17 | idsToTransAmount[i + 1] = mul * absAmount; 18 | } 19 | return idsToTransAmount; 20 | } 21 | 22 | std::map createBalanceForUsers(std::vector ids, 23 | int64_t balance) { 24 | std::vector transfers; 25 | std::map idsToBalances; 26 | for (auto id : ids) { 27 | transfers.emplace_back(hub::db:: 28 | UserTransfer{userId : id, amount : balance}); 29 | idsToBalances[id] = balance; 30 | } 31 | 32 | auto& connection = db::DBManager::get().connection(); 33 | connection.insertUserTransfers(transfers); 34 | return idsToBalances; 35 | } 36 | 37 | } // namespace tests 38 | } // namespace hub 39 | -------------------------------------------------------------------------------- /hub/commands/tests/helper.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #ifndef HUB_COMMANDS_TESTS_HELPER_H_ 4 | #define HUB_COMMANDS_TESTS_HELPER_H_ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "hub/commands/process_transfer_batch.h" 12 | #include "hub/tests/runner.h" 13 | 14 | namespace hub { 15 | 16 | namespace tests { 17 | std::map createBalanceForUsers(std::vector ids, 18 | int64_t balance); 19 | 20 | std::map createZigZagTransfer( 21 | std::vector& users, cmd::ProcessTransferBatchRequest& req, 22 | int64_t absAmount); 23 | 24 | } // namespace tests 25 | 26 | } // namespace hub 27 | #endif // HUB_COMMANDS_TESTS_HELPER_H_ 28 | -------------------------------------------------------------------------------- /hub/commands/tests/runner.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #ifndef HUB_COMMANDS_TESTS_RUNNER_H_ 4 | #define HUB_COMMANDS_TESTS_RUNNER_H_ 5 | 6 | #include 7 | 8 | #include "common/crypto/manager.h" 9 | #include "hub/commands/create_user.h" 10 | #include "hub/db/db.h" 11 | #include "hub/tests/runner.h" 12 | 13 | namespace hub { 14 | class CommandTest : public hub::Test { 15 | public: 16 | common::cmd::Error createUser(std::shared_ptr session, 17 | std::string username) { 18 | cmd::CreateUserRequest req; 19 | cmd::CreateUserReply res; 20 | 21 | req.userId = std::move(username); 22 | cmd::CreateUser command(std::move(session)); 23 | return command.process(&req, &res); 24 | } 25 | }; 26 | 27 | } // namespace hub 28 | #endif // HUB_COMMANDS_TESTS_RUNNER_H_ 29 | -------------------------------------------------------------------------------- /hub/commands/tests/test_balance_subscription.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "hub/commands/balance_subscription.h" 10 | #include "runner.h" 11 | 12 | using namespace testing; 13 | using namespace hub; 14 | using namespace hub::cmd; 15 | 16 | namespace { 17 | 18 | class BalanceSubscriptionTest : public CommandTest {}; 19 | 20 | class MockBalanceSubscription : public BalanceSubscription { 21 | public: 22 | using BalanceSubscription::BalanceSubscription; 23 | using BalanceSubscription::process; 24 | MOCK_METHOD1(getAllUsersAccountBalancesSinceTimePoint, 25 | std::vector( 26 | std::chrono::system_clock::time_point lastCheck)); 27 | MOCK_METHOD1(getAllUserAddressesBalancesSinceTimePoint, 28 | std::vector( 29 | std::chrono::system_clock::time_point lastCheck)); 30 | MOCK_METHOD1(getAllHubAddressesBalancesSinceTimePoint, 31 | std::vector( 32 | std::chrono::system_clock::time_point lastCheck)); 33 | }; 34 | 35 | TEST_F(BalanceSubscriptionTest, BalanceSubscriptionWriteAllEvents) { 36 | auto clientSession = std::make_shared(); 37 | MockBalanceSubscription mockCmd(clientSession); 38 | std::vector events; 39 | 40 | hub::cmd::BalanceSubscriptionRequest request; 41 | 42 | std::vector userAccountEvents; 43 | userAccountEvents.push_back(db::UserAccountBalanceEvent{}); 44 | userAccountEvents.push_back(db::UserAccountBalanceEvent{}); 45 | userAccountEvents.push_back(db::UserAccountBalanceEvent{}); 46 | userAccountEvents.push_back(db::UserAccountBalanceEvent{}); 47 | 48 | std::vector userAddressEvents; 49 | userAddressEvents.push_back(db::UserAddressBalanceEvent{}); 50 | userAddressEvents.push_back(db::UserAddressBalanceEvent{}); 51 | 52 | std::vector hubAddressEvents; 53 | hubAddressEvents.push_back(db::HubAddressBalanceEvent{}); 54 | hubAddressEvents.push_back(db::HubAddressBalanceEvent{}); 55 | 56 | EXPECT_CALL(mockCmd, getAllUsersAccountBalancesSinceTimePoint(_)) 57 | .Times(1) 58 | .WillOnce(Return(userAccountEvents)); 59 | EXPECT_CALL(mockCmd, getAllUserAddressesBalancesSinceTimePoint(_)) 60 | .Times(1) 61 | .WillOnce(Return(userAddressEvents)); 62 | EXPECT_CALL(mockCmd, getAllHubAddressesBalancesSinceTimePoint(_)) 63 | .Times(1) 64 | .WillOnce(Return(hubAddressEvents)); 65 | ASSERT_EQ(mockCmd.process(&request, &events), common::cmd::OK); 66 | } 67 | }; // namespace 68 | -------------------------------------------------------------------------------- /hub/commands/tests/test_create_user.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | 5 | #include "hub/commands/create_user.h" 6 | #include "runner.h" 7 | 8 | using namespace hub; 9 | using namespace sqlpp; 10 | 11 | namespace { 12 | class CreateUserTest : public CommandTest {}; 13 | 14 | TEST_F(CreateUserTest, ErrorOnDuplicate) { 15 | createUser(session(), "User1"); 16 | auto status = createUser(session(), "User1"); 17 | 18 | ASSERT_EQ(status, common::cmd::USER_EXISTS); 19 | } 20 | 21 | TEST_F(CreateUserTest, CreateUsers) { 22 | ASSERT_EQ(createUser(session(), "User1"), common::cmd::OK); 23 | ASSERT_EQ(createUser(session(), "User2"), common::cmd::OK); 24 | } 25 | 26 | }; // namespace 27 | -------------------------------------------------------------------------------- /hub/commands/tests/test_get_address_info.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | #include 5 | 6 | #include "common/crypto/types.h" 7 | #include "hub/commands/get_address_info.h" 8 | #include "hub/commands/get_deposit_address.h" 9 | #include "hub/db/helper.h" 10 | 11 | #include "runner.h" 12 | 13 | using namespace hub; 14 | using namespace sqlpp; 15 | using namespace testing; 16 | 17 | namespace { 18 | class GetAddressInfoTest : public CommandTest {}; 19 | 20 | TEST_F(GetAddressInfoTest, AddressCountInDatabaseShouldChange) { 21 | cmd::GetAddressInfoRequest req; 22 | cmd::GetAddressInfoReply res; 23 | cmd::GetDepositAddressRequest depReq; 24 | cmd::GetDepositAddressReply depRes; 25 | 26 | constexpr auto username = "User1"; 27 | 28 | createUser(session(), username); 29 | 30 | depReq.userId = username; 31 | 32 | cmd::GetDepositAddress depCommand(session()); 33 | cmd::GetAddressInfo command(session()); 34 | 35 | ASSERT_EQ(depCommand.process(&depReq, &depRes), common::cmd::OK); 36 | 37 | req.address = depRes.address.substr(0, common::crypto::Address::length()); 38 | ASSERT_EQ(command.process(&req, &res), common::cmd::OK); 39 | ASSERT_EQ(res.userId, username); 40 | } 41 | 42 | TEST_F(GetAddressInfoTest, InvalidOrUnknownAddressShouldFail) { 43 | cmd::GetAddressInfoRequest req; 44 | cmd::GetAddressInfoReply res; 45 | 46 | cmd::GetAddressInfo command(session()); 47 | 48 | req.address = "A"; 49 | ASSERT_NE(command.process(&req, &res), common::cmd::OK); 50 | 51 | req.address = 52 | "999999999999999999999999999999999999999999999999999999999999999999999999" 53 | "999999999"; 54 | ASSERT_NE(command.process(&req, &res), common::cmd::OK); 55 | req.address = 56 | "992999999999999999999999999999999999999999999999999999999999999999999999" 57 | "999999999"; 58 | ASSERT_NE(command.process(&req, &res), common::cmd::OK); 59 | } 60 | 61 | }; // namespace 62 | -------------------------------------------------------------------------------- /hub/commands/tests/test_get_balance.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | 5 | #include "hub/commands/get_balance.h" 6 | 7 | #include "runner.h" 8 | 9 | using namespace hub; 10 | using namespace sqlpp; 11 | 12 | namespace { 13 | class GetBalanceTest : public CommandTest {}; 14 | 15 | TEST_F(GetBalanceTest, UnknownUserShouldFail) { 16 | cmd::GetBalanceRequest req = {.userId = "User1"}; 17 | cmd::GetBalanceReply res; 18 | 19 | cmd::GetBalance command(session()); 20 | 21 | auto status = command.process(&req, &res); 22 | 23 | ASSERT_EQ(status, common::cmd::USER_DOES_NOT_EXIST); 24 | } 25 | 26 | TEST_F(GetBalanceTest, NewUserHasZeroBalance) { 27 | constexpr auto username = "User1"; 28 | cmd::GetBalanceRequest req = {.userId = username}; 29 | cmd::GetBalanceReply res; 30 | 31 | createUser(session(), username); 32 | 33 | cmd::GetBalance command(session()); 34 | 35 | ASSERT_EQ(command.process(&req, &res), common::cmd::OK); 36 | 37 | ASSERT_EQ(0, res.available); 38 | } 39 | 40 | }; // namespace 41 | -------------------------------------------------------------------------------- /hub/commands/tests/test_get_user_history.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | 5 | #include "hub/commands/get_user_history.h" 6 | #include "runner.h" 7 | 8 | using namespace hub; 9 | using namespace sqlpp; 10 | 11 | namespace { 12 | class GetUserHistoryTest : public CommandTest {}; 13 | 14 | TEST_F(GetUserHistoryTest, UnknownUserShouldFail) { 15 | hub::cmd::GetUserHistoryRequest req; 16 | hub::cmd::GetUserHistoryReply res; 17 | 18 | req.userId = "User1"; 19 | cmd::GetUserHistory command(session()); 20 | 21 | auto status = command.process(&req, &res); 22 | 23 | ASSERT_FALSE(status == common::cmd::OK); 24 | 25 | ASSERT_EQ(status, common::cmd::USER_DOES_NOT_EXIST); 26 | } 27 | 28 | TEST_F(GetUserHistoryTest, NewUserHasNoHistory) { 29 | hub::cmd::GetUserHistoryRequest req; 30 | hub::cmd::GetUserHistoryReply res; 31 | 32 | constexpr auto username = "User1"; 33 | 34 | createUser(session(), username); 35 | 36 | req.userId = username; 37 | 38 | cmd::GetUserHistory command(session()); 39 | 40 | ASSERT_EQ(command.process(&req, &res), common::cmd::OK); 41 | 42 | ASSERT_EQ(0, res.events.size()); 43 | } 44 | 45 | }; // namespace 46 | -------------------------------------------------------------------------------- /hub/commands/user_withdraw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_USER_WITHDRAW_H_ 9 | #define HUB_COMMANDS_USER_WITHDRAW_H_ 10 | 11 | #include 12 | 13 | #include "cppclient/api.h" 14 | 15 | #include "common/commands/command.h" 16 | 17 | namespace hub { 18 | namespace cmd { 19 | 20 | typedef struct UserWithdrawRequest { 21 | std::string userId; 22 | uint64_t amount; 23 | bool validateChecksum; 24 | std::string payoutAddress; 25 | std::string tag; 26 | } UserWithdrawRequest; 27 | typedef struct UserWithdrawReply { 28 | std::string uuid; 29 | } UserWithdrawReply; 30 | 31 | /// Process a withdrawal command for a user. 32 | /// @param[in] UserWithdrawRequest 33 | /// @param[in] rpc::UserWithdrawReply 34 | class UserWithdraw 35 | : public common::Command { 36 | public: 37 | using Command::Command; 38 | 39 | static std::shared_ptr create() { 40 | return std::shared_ptr( 41 | new UserWithdraw(std::make_shared())); 42 | } 43 | 44 | explicit UserWithdraw(std::shared_ptr session, 45 | std::shared_ptr api) 46 | : Command(std::move(session)), _api(std::move(api)) {} 47 | 48 | static const std::string name() { return "UserWithdraw"; } 49 | 50 | common::cmd::Error doProcess(const UserWithdrawRequest* request, 51 | UserWithdrawReply* response) noexcept override; 52 | 53 | boost::property_tree::ptree doProcess( 54 | const boost::property_tree::ptree& request) noexcept override; 55 | 56 | virtual bool needApi() const override { return true; } 57 | 58 | virtual void setApi(std::shared_ptr api) { _api = api; } 59 | 60 | private: 61 | std::shared_ptr _api; 62 | }; 63 | } // namespace cmd 64 | } // namespace hub 65 | 66 | #endif // HUB_COMMANDS_USER_WITHDRAW_H_ 67 | -------------------------------------------------------------------------------- /hub/commands/user_withdraw_cancel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_USER_WITHDRAW_CANCEL_H_ 9 | #define HUB_COMMANDS_USER_WITHDRAW_CANCEL_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | 17 | namespace cmd { 18 | 19 | typedef struct UserWithdrawCancelRequest { 20 | std::string uuid; 21 | } UserWithdrawCancelRequest; 22 | 23 | typedef struct UserWithdrawCancelReply { 24 | bool success; 25 | } UserWithdrawCancelReply; 26 | 27 | /// Cancels a previous withdrawal request if it hasn't been processed yet. 28 | /// @param[in] hub::rpc::UserWithdrawCancelRequest 29 | /// @param[in] hub::rpc::UserWithdrawCancelReply 30 | class UserWithdrawCancel : public common::Command { 32 | public: 33 | using Command::Command; 34 | 35 | static std::shared_ptr create() { 36 | return std::shared_ptr( 37 | new UserWithdrawCancel(std::make_shared())); 38 | } 39 | 40 | static const std::string name() { return "UserWithdrawCancel"; } 41 | 42 | common::cmd::Error doProcess( 43 | const UserWithdrawCancelRequest* request, 44 | UserWithdrawCancelReply* response) noexcept override; 45 | 46 | boost::property_tree::ptree doProcess( 47 | const boost::property_tree::ptree& request) noexcept override; 48 | }; 49 | } // namespace cmd 50 | } // namespace hub 51 | 52 | #endif // HUB_COMMANDS_USER_WITHDRAW_CANCEL_H_ 53 | -------------------------------------------------------------------------------- /hub/commands/was_address_spent_from.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_WAS_ADDRESS_SPENT_FROM_H_ 9 | #define HUB_COMMANDS_WAS_ADDRESS_SPENT_FROM_H_ 10 | 11 | #include 12 | 13 | #include "cppclient/api.h" 14 | 15 | #include "common/commands/command.h" 16 | 17 | namespace hub { 18 | 19 | namespace cmd { 20 | 21 | typedef struct WasAddressSpentFromRequest { 22 | std::string address; 23 | bool validateChecksum; 24 | } WasAddressSpentFromRequest; 25 | 26 | typedef struct WasAddressSpentFromReply { 27 | bool wasAddressSpentFrom; 28 | } WasAddressSpentFromReply; 29 | 30 | /// Returns whether or not an address was spent. 31 | /// @param[in] WasAddressSpentFromRequest 32 | /// @param[in] WasAddressSpentFromReply 33 | class WasAddressSpentFrom : public common::Command { 35 | public: 36 | using Command::Command; 37 | 38 | static std::shared_ptr create() { 39 | return std::shared_ptr( 40 | new WasAddressSpentFrom(std::make_shared())); 41 | } 42 | 43 | explicit WasAddressSpentFrom(std::shared_ptr session, 44 | std::shared_ptr api) 45 | : Command(std::move(session)), _api(std::move(api)) {} 46 | 47 | static const std::string name() { return "WasAddressSpentFrom"; } 48 | 49 | common::cmd::Error doProcess( 50 | const WasAddressSpentFromRequest* request, 51 | WasAddressSpentFromReply* response) noexcept override; 52 | 53 | boost::property_tree::ptree doProcess( 54 | const boost::property_tree::ptree& request) noexcept override; 55 | 56 | virtual bool needApi() const override { return true; } 57 | 58 | virtual void setApi(std::shared_ptr api) { _api = api; } 59 | 60 | private: 61 | std::shared_ptr _api; 62 | }; 63 | } // namespace cmd 64 | } // namespace hub 65 | 66 | #endif // HUB_COMMANDS_WAS_ADDRESS_SPENT_FROM_H_ 67 | -------------------------------------------------------------------------------- /hub/commands/was_withdrawal_cancelled.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "common/converter.h" 15 | 16 | #include "hub/commands/factory.h" 17 | #include "hub/commands/helper.h" 18 | #include "hub/db/helper.h" 19 | 20 | #include "hub/commands/was_withdrawal_cancelled.h" 21 | 22 | namespace hub { 23 | namespace cmd { 24 | 25 | static CommandFactoryRegistrator registrator; 26 | 27 | boost::property_tree::ptree WasWithdrawalCancelled::doProcess( 28 | const boost::property_tree::ptree& request) noexcept { 29 | boost::property_tree::ptree tree; 30 | WasWithdrawalCancelledRequest req; 31 | WasWithdrawalCancelledReply rep; 32 | auto maybeUuid = request.get_optional("uuid"); 33 | if (!maybeUuid) { 34 | tree.add("error", 35 | common::cmd::getErrorString(common::cmd::MISSING_ARGUMENT)); 36 | return tree; 37 | } 38 | 39 | req.uuid = maybeUuid.value(); 40 | 41 | auto status = doProcess(&req, &rep); 42 | 43 | if (status != common::cmd::OK) { 44 | tree.add("error", common::cmd::getErrorString(status)); 45 | } else { 46 | tree.add("wasCancelled", 47 | std::move(common::boolToString(rep.wasWihdrawalCancelled))); 48 | } 49 | 50 | return tree; 51 | } 52 | 53 | common::cmd::Error WasWithdrawalCancelled::doProcess( 54 | const WasWithdrawalCancelledRequest* request, 55 | WasWithdrawalCancelledReply* response) noexcept { 56 | auto& connection = db::DBManager::get().connection(); 57 | 58 | try { 59 | boost::uuids::uuid uuid = boost::uuids::string_generator()(request->uuid); 60 | 61 | auto withdrawalInfo = 62 | connection.getWithdrawalInfoFromUUID(boost::uuids::to_string(uuid)); 63 | 64 | response->wasWihdrawalCancelled = withdrawalInfo.wasCancelled; 65 | 66 | } catch (const std::exception& ex) { 67 | LOG(ERROR) << session() << " Query failed: " << ex.what(); 68 | return common::cmd::INVALID_UUID; 69 | } 70 | 71 | return common::cmd::OK; 72 | } // namespace cmd 73 | 74 | } // namespace cmd 75 | } // namespace hub 76 | -------------------------------------------------------------------------------- /hub/commands/was_withdrawal_cancelled.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_COMMANDS_WAS_WITHDRAWAL_CANCELLED_H_ 9 | #define HUB_COMMANDS_WAS_WITHDRAWAL_CANCELLED_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace hub { 16 | namespace cmd { 17 | 18 | typedef struct WasWithdrawalCancelledRequest { 19 | std::string uuid; 20 | } WasWithdrawalCancelledRequest; 21 | 22 | typedef struct WasWithdrawalCancelledReply { 23 | bool wasWihdrawalCancelled; 24 | } WasWithdrawalCancelledReply; 25 | 26 | /// Returns true if withdrawal was cancelled 27 | /// @param[in] request - a WasWithdrawalCancelledRequest request 28 | /// @param[in] response - a WasWithdrawalCancelledResponse response 29 | class WasWithdrawalCancelled 30 | : public common::Command { 32 | public: 33 | using Command::Command; 35 | 36 | static std::shared_ptr create() { 37 | return std::shared_ptr( 38 | new WasWithdrawalCancelled(std::make_shared())); 39 | } 40 | 41 | static const std::string name() { return "WasWithdrawalCancelled"; } 42 | 43 | common::cmd::Error doProcess( 44 | const WasWithdrawalCancelledRequest* request, 45 | WasWithdrawalCancelledReply* response) noexcept override; 46 | 47 | boost::property_tree::ptree doProcess( 48 | const boost::property_tree::ptree& request) noexcept override; 49 | }; 50 | } // namespace cmd 51 | } // namespace hub 52 | 53 | #endif // HUB_COMMANDS_WAS_WITHDRAWAL_CANCELLED_H_ 54 | -------------------------------------------------------------------------------- /hub/crypto/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "local_signing_provider", 3 | srcs = ["local_provider.cc"], 4 | hdrs = [ 5 | "local_provider.h", 6 | ], 7 | visibility = ["//visibility:public"], 8 | deps = [ 9 | "//common", 10 | "//common/crypto:argon2_provider", 11 | "//hub/db", 12 | ], 13 | ) 14 | 15 | cc_library( 16 | name = "remote_signing_server", 17 | srcs = ["remote_signing_provider.cc"], 18 | hdrs = [ 19 | "remote_signing_provider.h", 20 | ], 21 | visibility = ["//visibility:public"], 22 | deps = [ 23 | "//common", 24 | "//common/crypto", 25 | "//hub/db", 26 | "//proto:signing_server_grpc_cc", 27 | "@optional_lite", 28 | ], 29 | ) 30 | 31 | cc_library( 32 | name = "signing", 33 | visibility = ["//visibility:public"], 34 | deps = [ 35 | ":local_signing_provider", 36 | ":remote_signing_server", 37 | ], 38 | ) 39 | 40 | cc_test( 41 | name = "test_crypto", 42 | srcs = glob([ 43 | "tests/**/*.cc", 44 | ]), 45 | deps = [ 46 | ":local_signing_provider", 47 | "//common/tests", 48 | "//hub/tests", 49 | "@boost//:interprocess", 50 | "@com_google_googletest//:gtest", 51 | ], 52 | ) 53 | -------------------------------------------------------------------------------- /hub/crypto/local_provider.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/crypto/local_provider.h" 9 | 10 | namespace hub { 11 | namespace crypto { 12 | nonstd::optional LocalSigningProvider::getSignatureForUUID( 13 | const common::crypto::UUID& uuid, 14 | const common::crypto::Hash& bundleHash) const { 15 | auto& connection = db::DBManager::get().connection(); 16 | 17 | connection.markUUIDAsSigned(uuid); 18 | 19 | return doGetSignatureForUUID(uuid, bundleHash); 20 | } 21 | } // namespace crypto 22 | } // namespace hub 23 | -------------------------------------------------------------------------------- /hub/crypto/local_provider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_CRYPTO_LOCAL_PROVIDER_H_ 9 | #define HUB_CRYPTO_LOCAL_PROVIDER_H_ 10 | 11 | #include 12 | 13 | #include "common/crypto/argon2_provider.h" 14 | #include "common/crypto/types.h" 15 | #include "hub/db/helper.h" 16 | 17 | namespace hub { 18 | namespace crypto { 19 | 20 | /// LocalSigningProvider class. 21 | /// Provides the cryptographic services necessary to 22 | /// obtain new addresses based on salt and sign bundle hashes. 23 | class LocalSigningProvider : public common::crypto::Argon2Provider { 24 | public: 25 | /// Calculate the signature for a UUID and a bundle hash 26 | /// param[in] connection - connection to the local database 27 | /// param[in] UUID - a UUID 28 | /// param[in] Hash - a bundleHash 29 | /// @throws sqlpp::exception if UUID was already used for a signature 30 | /// @return string - the signature 31 | nonstd::optional getSignatureForUUID( 32 | const common::crypto::UUID& uuid, 33 | const common::crypto::Hash& bundleHash) const override; 34 | 35 | explicit LocalSigningProvider(const std::string& salt) 36 | : Argon2Provider(salt) {} 37 | }; 38 | 39 | } // namespace crypto 40 | } // namespace hub 41 | #endif // HUB_CRYPTO_LOCAL_PROVIDER_H_ 42 | -------------------------------------------------------------------------------- /hub/crypto/remote_signing_provider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_CRYPTO_REMOTE_SIGNING_PROVIDER_H_ 9 | #define HUB_CRYPTO_REMOTE_SIGNING_PROVIDER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "common/crypto/provider_base.h" 17 | #include "hub/db/db.h" 18 | #include "proto/signing_server.grpc.pb.h" 19 | #include "proto/signing_server.pb.h" 20 | 21 | namespace hub { 22 | namespace crypto { 23 | 24 | class RemoteSigningProvider : public common::crypto::CryptoProviderBase { 25 | public: 26 | /// Constructor 27 | /// param[in] url - the url for the grpc service 28 | explicit RemoteSigningProvider(const std::string& url, 29 | const std::string& certPath, 30 | const std::string& chainPath, 31 | const std::string& keyPath); 32 | 33 | /// Get a new address for a given UUID and the salt 34 | /// param[in] UUID - a UUID 35 | nonstd::optional getAddressForUUID( 36 | const common::crypto::UUID& uuid) const override; 37 | 38 | /// The current security level 39 | /// @return size_t - the security level (1 - 3) 40 | nonstd::optional securityLevel( 41 | const common::crypto::UUID& uuid) const override; 42 | 43 | nonstd::optional getSignatureForUUID( 44 | const common::crypto::UUID& uuid, 45 | const common::crypto::Hash& bundleHash) const override { 46 | auto& connection = hub::db::DBManager::get().connection(); 47 | connection.markUUIDAsSigned(uuid); 48 | 49 | return doGetSignatureForUUID(uuid, bundleHash); 50 | } 51 | 52 | /// Calculate the seed for a UUID. 53 | /// param[in] UUID - a UUID 54 | /// @return string - the seed 55 | 56 | virtual std::string getSeedFromUUID( 57 | const common::crypto::UUID& uuid) const override; 58 | 59 | protected: 60 | /// Calculate the signature for a UUID and a bundle hash 61 | /// param[in] UUID - a UUID 62 | /// param[in] Hash - a bundleHash 63 | /// @return string - the signature 64 | nonstd::optional doGetSignatureForUUID( 65 | const common::crypto::UUID& uuid, 66 | const common::crypto::Hash& bundleHash) const override; 67 | 68 | private: 69 | std::unique_ptr _stub; 70 | }; 71 | 72 | } // namespace crypto 73 | } // namespace hub 74 | #endif // HUB_CRYPTO_REMOTE_SIGNING_PROVIDER_H_ 75 | -------------------------------------------------------------------------------- /hub/db/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "db", 3 | srcs = glob( 4 | ["**/*.cc"], 5 | exclude = ["tests/**/*"], 6 | ), 7 | hdrs = glob( 8 | ["**/*.h"], 9 | exclude = ["tests/**/*"], 10 | ), 11 | visibility = ["//visibility:public"], 12 | deps = [ 13 | "//common/crypto:types", 14 | "//schema", 15 | "@boost//:uuid", 16 | "@com_github_gflags_gflags//:gflags", 17 | "@com_github_google_glog//:glog", 18 | "@optional_lite", 19 | "@sqlpp11", 20 | "@sqlpp11mysql", 21 | "@sqlpp11sqlite", 22 | ], 23 | ) 24 | 25 | cc_test( 26 | name = "test_db", 27 | srcs = glob([ 28 | "tests/**/*.cc", 29 | ]), 30 | deps = [ 31 | ":db", 32 | "//hub/tests", 33 | "@com_google_googletest//:gtest", 34 | ], 35 | timeout = "moderate" 36 | ) 37 | -------------------------------------------------------------------------------- /hub/db/CPPLINT.cfg: -------------------------------------------------------------------------------- 1 | filter=-runtime/references -------------------------------------------------------------------------------- /hub/db/db.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_DB_DB_H_ 9 | #define HUB_DB_DB_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include "hub/db/connection.h" 19 | #include "hub/db/types.h" 20 | 21 | namespace hub { 22 | namespace db { 23 | DECLARE_string(db); 24 | 25 | struct Config { 26 | std::string type; 27 | 28 | std::string host; 29 | uint32_t port; 30 | std::string database; 31 | 32 | std::string user; 33 | std::string password; 34 | 35 | bool debug{false}; 36 | }; 37 | 38 | class Connection; 39 | 40 | /*** 41 | This class manages access to the database connection. 42 | It currently creates one connection per thread. 43 | ***/ 44 | class DBManager { 45 | private: 46 | DBManager() {} 47 | 48 | DBManager(DBManager const&) = delete; 49 | DBManager(DBManager&&) = delete; 50 | DBManager& operator=(DBManager const&) = delete; 51 | DBManager& operator=(DBManager&&) = delete; 52 | 53 | public: 54 | static DBManager& get(); 55 | 56 | //! Loads schema 57 | void loadSchema(); 58 | 59 | void resetConnection(); 60 | 61 | void loadConnectionConfigFromArgs(); 62 | void setConnectionConfig(Config config) { _config = std::move(config); } 63 | const Config& config() const { return _config; } 64 | 65 | hub::db::Connection& connection(); 66 | 67 | protected: 68 | void executeFile(const std::string& fname); 69 | 70 | private: 71 | Config _config; 72 | }; 73 | 74 | } // namespace db 75 | } // namespace hub 76 | 77 | #endif // HUB_DB_DB_H_ 78 | -------------------------------------------------------------------------------- /hub/db/mariadb.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include "hub/db/db.h" 14 | #include "hub/db/mariadb.h" 15 | 16 | namespace hub { 17 | namespace db { 18 | 19 | namespace mysql = sqlpp::mysql; 20 | 21 | template <> 22 | std::unique_ptr 23 | ConnectionImpl::fromConfig( 24 | const Config& config) { 25 | auto db = std::make_shared(); 26 | db->debug = config.debug; 27 | 28 | db->user = config.user; 29 | db->password = config.password; 30 | db->host = config.host; 31 | db->port = config.port; 32 | db->database = config.database; 33 | 34 | auto conn = std::make_unique(std::move(db)); 35 | conn->execute("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE"); 36 | 37 | return conn; 38 | } 39 | 40 | } // namespace db 41 | } // namespace hub 42 | -------------------------------------------------------------------------------- /hub/db/mariadb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_DB_MARIADB_H_ 9 | #define HUB_DB_MARIADB_H_ 10 | 11 | #include 12 | 13 | #include "hub/db/connection.h" 14 | #include "hub/db/connection_impl.h" 15 | 16 | namespace hub { 17 | namespace db { 18 | 19 | class MariaDBConnection 20 | : public ConnectionImpl { 22 | using ConnectionImpl::ConnectionImpl; 24 | }; 25 | 26 | } // namespace db 27 | } // namespace hub 28 | 29 | #endif // HUB_DB_MARIADB_H_ 30 | -------------------------------------------------------------------------------- /hub/db/sqlite3.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "hub/db/db.h" 13 | 14 | #include "hub/db/sqlite3.h" 15 | 16 | namespace hub { 17 | namespace db { 18 | 19 | namespace sqlite = sqlpp::sqlite3; 20 | 21 | template <> 22 | std::unique_ptr 23 | ConnectionImpl::fromConfig( 24 | const Config& config) { 25 | sqlite::connection_config db; 26 | 27 | db.debug = config.debug; 28 | db.path_to_database = config.database; 29 | db.flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; 30 | 31 | auto conn = std::make_unique(db); 32 | conn->set_default_isolation_level(sqlpp::isolation_level::serializable); 33 | conn->execute("PRAGMA journal_mode = WAL"); 34 | conn->execute("PRAGMA foreign_keys = ON"); 35 | conn->execute("PRAGMA busy_timeout = 10000"); 36 | 37 | return conn; 38 | } 39 | 40 | } // namespace db 41 | } // namespace hub 42 | -------------------------------------------------------------------------------- /hub/db/sqlite3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_DB_SQLITE3_H_ 9 | #define HUB_DB_SQLITE3_H_ 10 | 11 | #include 12 | 13 | #include "hub/db/connection.h" 14 | #include "hub/db/connection_impl.h" 15 | 16 | namespace hub { 17 | namespace db { 18 | 19 | class SQLite3Connection 20 | : public ConnectionImpl { 22 | using ConnectionImpl::ConnectionImpl; 24 | }; 25 | 26 | } // namespace db 27 | } // namespace hub 28 | 29 | #endif // HUB_DB_SQLITE3_H_ 30 | -------------------------------------------------------------------------------- /hub/iota/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "remote_pow", 3 | hdrs = ["remote_pow.h"], 4 | visibility = ["//visibility:public"], 5 | deps = [":pow"], 6 | ) 7 | 8 | cc_library( 9 | name = "local_pow", 10 | srcs = ["local_pow.cc"], 11 | hdrs = ["local_pow.h"], 12 | visibility = ["//visibility:public"], 13 | deps = [ 14 | ":pow", 15 | "@org_iota_common//common/helpers:pow", 16 | "@org_iota_common//common/model:bundle", 17 | "@org_iota_common//common/trinary:tryte_long", 18 | ], 19 | ) 20 | 21 | cc_library( 22 | name = "pow", 23 | srcs = ["pow.cc"], 24 | hdrs = ["pow.h"], 25 | visibility = ["//visibility:public"], 26 | deps = ["@TangleScope//cppclient:beast"], 27 | ) 28 | 29 | cc_test( 30 | name = "tests", 31 | srcs = glob(["tests/**/*.cc"]), 32 | deps = [ 33 | ":local_pow", 34 | "//hub/tests", 35 | "@com_google_googletest//:gtest", 36 | ], 37 | ) 38 | -------------------------------------------------------------------------------- /hub/iota/local_pow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_IOTA_LOCAL_POW_H_ 9 | #define HUB_IOTA_LOCAL_POW_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "hub/iota/pow.h" 18 | 19 | namespace hub { 20 | namespace iota { 21 | 22 | class LocalPOW : public POWProvider { 23 | public: 24 | using POWProvider::POWProvider; 25 | 26 | LocalPOW(std::shared_ptr api, size_t depth, size_t mwm); 27 | 28 | static constexpr uint16_t OBSOLETE_TAG_OFFSET = 2295; 29 | static constexpr uint16_t TIMESTAMP_OFFSET = 2322; 30 | static constexpr uint16_t TRUNK_OFFSET = 2430; 31 | static constexpr uint16_t BRANCH_OFFSET = 2511; 32 | static constexpr uint16_t TAG_OFFSET = 2592; 33 | static constexpr uint16_t NONCE_OFFSET = 2646; 34 | 35 | protected: 36 | std::vector doPOW(const std::vector& trytes, 37 | const std::string& trunk, 38 | const std::string& branch) const override; 39 | }; 40 | } // namespace iota 41 | } // namespace hub 42 | 43 | #endif // HUB_IOTA_LOCAL_POW_H_ 44 | -------------------------------------------------------------------------------- /hub/iota/pow.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/iota/pow.h" 9 | 10 | namespace hub { 11 | namespace iota { 12 | 13 | POWManager& POWManager::get() { 14 | static POWManager instance; 15 | return instance; 16 | } 17 | 18 | nonstd::optional 19 | POWProvider::getAttachmentPoint( 20 | const nonstd::optional& reference) const { 21 | return _api->getTransactionsToApprove(_depth, reference); 22 | } 23 | 24 | } // namespace iota 25 | } // namespace hub 26 | -------------------------------------------------------------------------------- /hub/iota/pow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_IOTA_POW_H_ 9 | #define HUB_IOTA_POW_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "cppclient/api.h" 19 | 20 | namespace hub { 21 | namespace iota { 22 | 23 | /// POWProvider (Proof Of Work provider) 24 | class POWProvider { 25 | public: 26 | /// Constructor 27 | POWProvider(std::shared_ptr api, size_t depth, size_t mwm) 28 | : _api(std::move(api)), _depth(depth), _mwm(mwm) {} 29 | 30 | /// Destructor 31 | virtual ~POWProvider() {} 32 | 33 | size_t mwm() const { return _mwm; } 34 | size_t depth() const { return _depth; } 35 | 36 | virtual nonstd::optional 37 | getAttachmentPoint(const nonstd::optional& reference) const; 38 | 39 | virtual std::vector performPOW( 40 | const std::vector& trytes) const { 41 | auto maybeLocation = getAttachmentPoint({}); 42 | if (!maybeLocation) { 43 | LOG(ERROR) << "Failed to get attachment point"; 44 | return {}; 45 | } 46 | 47 | auto location = maybeLocation.value(); 48 | return doPOW(trytes, location.trunkTransaction, location.branchTransaction); 49 | } 50 | 51 | virtual std::vector doPOW(const std::vector& trytes, 52 | const std::string& trunk, 53 | const std::string& branch) const = 0; 54 | 55 | protected: 56 | const std::shared_ptr _api; 57 | const size_t _depth; 58 | const size_t _mwm; 59 | }; 60 | 61 | class POWManager { 62 | private: 63 | POWManager() = default; 64 | 65 | public: 66 | static POWManager& get(); 67 | 68 | POWProvider& provider() { return *_provider; } 69 | 70 | void setProvider(std::unique_ptr provider) { 71 | _provider = std::move(provider); 72 | } 73 | 74 | private: 75 | std::unique_ptr _provider; 76 | }; 77 | 78 | } // namespace iota 79 | } // namespace hub 80 | 81 | #endif // HUB_IOTA_POW_H_ 82 | -------------------------------------------------------------------------------- /hub/iota/remote_pow.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_IOTA_REMOTE_POW_H_ 9 | #define HUB_IOTA_REMOTE_POW_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "cppclient/api.h" 18 | #include "hub/iota/pow.h" 19 | 20 | namespace hub { 21 | namespace iota { 22 | 23 | class RemotePOW : public POWProvider { 24 | public: 25 | using POWProvider::POWProvider; 26 | 27 | protected: 28 | std::vector doPOW(const std::vector& trytes, 29 | const std::string& trunk, 30 | const std::string& branch) const override { 31 | return _api->attachToTangle(trunk, branch, mwm(), trytes); 32 | } 33 | }; 34 | } // namespace iota 35 | } // namespace hub 36 | 37 | #endif // HUB_IOTA_REMOTE_POW_H_ 38 | -------------------------------------------------------------------------------- /hub/main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "hub/server/grpc_server.h" 12 | #include "hub/server/http_json_server.h" 13 | 14 | int main(int argc, char** argv) { 15 | google::InstallFailureSignalHandler(); 16 | 17 | auto programName = argc && argv && argc > 0 ? argv[0] : "unknown"; 18 | google::InitGoogleLogging(programName); 19 | gflags::ParseCommandLineFlags(&argc, &argv, true); 20 | 21 | LOG(INFO) << "Hub starting up."; 22 | 23 | std::shared_ptr server; 24 | 25 | if (FLAGS_serverType == "http") { 26 | server.reset(new hub::HubHttpJsonServer()); 27 | } else if (FLAGS_serverType == "grpc") { 28 | server.reset(new hub::HubGrpcServer()); 29 | } else { 30 | LOG(FATAL) << "Unknown server type"; 31 | } 32 | 33 | server->initialize(); 34 | server->runAndWait(); 35 | } 36 | -------------------------------------------------------------------------------- /hub/server/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "server", 3 | srcs = glob(["**/*.cc"]), 4 | hdrs = glob(["**/*.h"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//common", 8 | "//common/crypto", 9 | "//common/stats", 10 | "//hub/auth", 11 | "//hub/auth:dummy_provider", 12 | "//hub/auth:hmac_provider", 13 | "//hub/commands", 14 | "//hub/crypto:signing", 15 | "//hub/db", 16 | "//hub/iota:local_pow", 17 | "//hub/iota:pow", 18 | "//hub/iota:remote_pow", 19 | "//hub/service:attachment_service", 20 | "//hub/service:sweep_service", 21 | "//hub/service:user_address_monitor", 22 | "//proto:hub_grpc_cc", 23 | "@boost//:property_tree", 24 | "@com_github_google_glog//:glog", 25 | "@TangleScope//cppclient:beast", 26 | ], 27 | ) 28 | -------------------------------------------------------------------------------- /hub/server/grpc_server.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/server/grpc_server.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include "common/common.h" 14 | #include "common/crypto/argon2_provider.h" 15 | #include "common/crypto/manager.h" 16 | #include "common/flags.h" 17 | #include "cppclient/beast.h" 18 | #include "hub/auth/dummy_provider.h" 19 | #include "hub/auth/hmac_provider.h" 20 | #include "hub/auth/manager.h" 21 | #include "hub/crypto/local_provider.h" 22 | #include "hub/crypto/remote_signing_provider.h" 23 | #include "hub/db/db.h" 24 | #include "hub/db/helper.h" 25 | #include "hub/iota/local_pow.h" 26 | #include "hub/iota/pow.h" 27 | #include "hub/iota/remote_pow.h" 28 | #include "hub/service/sweep_service.h" 29 | #include "hub/service/user_address_monitor.h" 30 | 31 | using grpc::Server; 32 | using grpc::ServerBuilder; 33 | 34 | namespace hub { 35 | HubGrpcServer::HubGrpcServer() {} 36 | 37 | void HubGrpcServer::initialize() { 38 | initialize_services(); 39 | 40 | _service.setApi(_api); 41 | 42 | ServerBuilder builder; 43 | 44 | builder.AddListeningPort( 45 | common::flags::FLAGS_listenAddress, 46 | makeCredentials(common::flags::FLAGS_authMode, 47 | common::flags::FLAGS_sslCert, common::flags::FLAGS_sslKey, 48 | common::flags::FLAGS_sslCA)); 49 | builder.RegisterService(&_service); 50 | 51 | _server = builder.BuildAndStart(); 52 | 53 | LOG(INFO) << "Server listening on " << common::flags::FLAGS_listenAddress; 54 | } 55 | 56 | } // namespace hub 57 | -------------------------------------------------------------------------------- /hub/server/grpc_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVER_GRPC_SERVER_H_ 9 | #define HUB_SERVER_GRPC_SERVER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "common/grpc_server_base.h" 17 | #include "cppclient/api.h" 18 | #include "hub/server/grpc.h" 19 | #include "hub/service/attachment_service.h" 20 | #include "hub/service/sweep_service.h" 21 | #include "hub/service/user_address_monitor.h" 22 | #include "hub_server_base.h" 23 | #include "proto/hub.grpc.pb.h" 24 | #include "proto/hub.pb.h" 25 | 26 | namespace hub { 27 | 28 | /// HubServer class. 29 | /// The HubServer runs the local services and holds the instance of the 30 | /// cppclient::IotaAPI complient API interface to the tangle. It also holds 31 | /// an instance of the hub service that will accept requests 32 | class HubGrpcServer : public common::GrpcServerBase, public HubServerBase { 33 | public: 34 | /// Constructor. 35 | HubGrpcServer(); 36 | 37 | /// Creates and initializes the services and the API interface. 38 | void initialize() override; 39 | 40 | private: 41 | /// The hub::HubImpl service that listens to requests from clients 42 | hub::HubImpl _service; 43 | }; 44 | 45 | } // namespace hub 46 | #endif // HUB_SERVER_GRPC_SERVER_H_ 47 | -------------------------------------------------------------------------------- /hub/server/http_json_server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVER_HTTP_SERVER_H_ 9 | #define HUB_SERVER_HTTP_SERVER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "common/http_server_base.h" 15 | #include "cppclient/api.h" 16 | #include "hub/server/hub_server_base.h" 17 | #include "hub/service/attachment_service.h" 18 | #include "hub/service/sweep_service.h" 19 | #include "hub/service/user_address_monitor.h" 20 | 21 | namespace hub { 22 | 23 | /// HubServer class. 24 | /// The HubServer runs the local services and holds the instance of the 25 | /// cppclient::IotaAPI complient API interface to the tangle. It also holds 26 | /// an instance of the hub service that will accept requests 27 | class HubHttpJsonServer : public common::HttpServerBase, public HubServerBase { 28 | public: 29 | /// Constructor. 30 | HubHttpJsonServer(); 31 | 32 | /// Creates and initializes the services and the API interface. 33 | void initialize() override; 34 | virtual ErrorCode handleRequestImpl(std::string_view request_body, 35 | std::string& response) override; 36 | 37 | private: 38 | }; 39 | 40 | } // namespace hub 41 | #endif // HUB_SERVER_HTTP_SERVER_H_ 42 | -------------------------------------------------------------------------------- /hub/server/hub_server_base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVER_HUB_SERVER_H_ 9 | #define HUB_SERVER_HUB_SERVER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include "cppclient/api.h" 16 | #include "hub/service/attachment_service.h" 17 | #include "hub/service/sweep_service.h" 18 | #include "hub/service/user_address_monitor.h" 19 | 20 | DECLARE_string(apiAddress); 21 | 22 | DECLARE_uint32(monitorInterval); 23 | DECLARE_uint32(attachmentInterval); 24 | DECLARE_uint32(sweepInterval); 25 | 26 | DECLARE_uint32(minWeightMagnitude); 27 | DECLARE_uint32(depth); 28 | 29 | DECLARE_string(hmacKeyPath); 30 | DECLARE_string(authProvider); 31 | 32 | // remote crypto provider settings 33 | DECLARE_string(signingMode); 34 | DECLARE_string(signingProviderAddress); 35 | // The following credentials components has to match those of the SigningServer 36 | DECLARE_string(signingServerSslCert); 37 | DECLARE_string(signingServerChainCert); 38 | DECLARE_string(signingServerKeyCert); 39 | 40 | // remote/local pow settings 41 | DECLARE_string(powMode); 42 | 43 | // Extended 44 | DECLARE_bool(fetchTransactionMessages); 45 | 46 | DECLARE_bool(useHttpsIRI); 47 | 48 | // GRPC/Http Rest 49 | DECLARE_string(serverType); 50 | 51 | namespace hub { 52 | 53 | /// HubServer class. 54 | /// The HubServer runs the local services and holds the instance of the 55 | /// cppclient::IotaAPI complient API interface to the tangle. It also holds 56 | /// an instance of the hub service that will accept requests 57 | class HubServerBase { 58 | public: 59 | /// Constructor. 60 | HubServerBase(); 61 | 62 | /// Creates and initializes the services and the API interface. 63 | void initialize_services(); 64 | 65 | protected: 66 | std::shared_ptr _api; 67 | 68 | private: 69 | std::unique_ptr _userAddressMonitor; 70 | std::unique_ptr _attachmentService; 71 | std::unique_ptr _sweepService; 72 | 73 | /// Verifies that the salt provided on the command line has the correct 74 | /// value for this server. Will always succeed if no user addresses exist 75 | /// in the database. 76 | /// @return bool - true on success 77 | bool authenticateSalt() const; 78 | 79 | void initialiseAuthProvider() const; 80 | }; 81 | 82 | } // namespace hub 83 | #endif // HUB_SERVER_HUB_SERVER_H_ 84 | -------------------------------------------------------------------------------- /hub/service/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "service", 3 | srcs = ["service.cc"], 4 | hdrs = ["service.h"], 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "@boost//:asio", 8 | "@boost//:bind", 9 | ], 10 | ) 11 | 12 | cc_library( 13 | name = "attachment_service", 14 | srcs = ["attachment_service.cc"], 15 | hdrs = ["attachment_service.h"], 16 | visibility = ["//visibility:public"], 17 | deps = [ 18 | ":scheduled_service", 19 | "//hub/db", 20 | "//hub/iota:pow", 21 | "@TangleScope//cppclient:beast", 22 | "@boost//:functional", 23 | "@boost//:range", 24 | "@com_github_google_glog//:glog", 25 | "@org_iota_common//common/helpers:digest", 26 | "@org_iota_common//common/model:bundle", 27 | ], 28 | ) 29 | 30 | cc_library( 31 | name = "sweep_service", 32 | srcs = ["sweep_service.cc"], 33 | hdrs = ["sweep_service.h"], 34 | visibility = ["//visibility:public"], 35 | deps = [ 36 | ":scheduled_service", 37 | "//hub/bundle:bundle_utils", 38 | "@TangleScope//cppclient:beast", 39 | "@boost//:range", 40 | "@boost//:uuid", 41 | ], 42 | ) 43 | 44 | cc_library( 45 | name = "address_monitor", 46 | srcs = ["address_monitor.cc"], 47 | hdrs = ["address_monitor.h"], 48 | visibility = ["//visibility:public"], 49 | deps = [ 50 | ":scheduled_service", 51 | "@TangleScope//cppclient:beast", 52 | "@com_github_google_glog//:glog", 53 | ], 54 | ) 55 | 56 | cc_library( 57 | name = "user_address_monitor", 58 | srcs = ["user_address_monitor.cc"], 59 | hdrs = ["user_address_monitor.h"], 60 | visibility = ["//visibility:public"], 61 | deps = [ 62 | ":address_monitor", 63 | "//hub/db", 64 | "@boost//:move", 65 | "@boost//:range", 66 | ], 67 | ) 68 | 69 | cc_library( 70 | name = "scheduled_service", 71 | srcs = ["scheduled_service.cc"], 72 | hdrs = ["scheduled_service.h"], 73 | visibility = ["//visibility:public"], 74 | deps = [ 75 | ":service", 76 | "@boost//:asio", 77 | "@com_github_google_glog//:glog", 78 | ], 79 | ) 80 | 81 | cc_test( 82 | name = "tests", 83 | srcs = glob(["tests/**/*.cc"]), 84 | deps = [ 85 | ":address_monitor", 86 | ":scheduled_service", 87 | ":sweep_service", 88 | ":user_address_monitor", 89 | "//hub/tests", 90 | "@com_google_googletest//:gtest", 91 | ], 92 | ) 93 | -------------------------------------------------------------------------------- /hub/service/CPPLINT.cfg: -------------------------------------------------------------------------------- 1 | filter=-runtime/references -------------------------------------------------------------------------------- /hub/service/attachment_service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVICE_ATTACHMENT_SERVICE_H_ 9 | #define HUB_SERVICE_ATTACHMENT_SERVICE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "cppclient/api.h" 18 | #include "hub/db/db.h" 19 | #include "hub/iota/pow.h" 20 | #include "hub/service/scheduled_service.h" 21 | 22 | namespace hub { 23 | namespace db { 24 | struct Sweep; 25 | struct SweepTail; 26 | } // namespace db 27 | 28 | namespace service { 29 | 30 | /// AttachmentService class. 31 | class AttachmentService : public ScheduledService { 32 | public: 33 | /// constructor 34 | /// @param[in] api - an cppclient::IotaAPI compliant API provider 35 | /// @param[in] interval - the tick interval in milliseconds 36 | explicit AttachmentService(std::shared_ptr api, 37 | std::chrono::milliseconds interval) 38 | : ScheduledService(interval), _api(std::move(api)) {} 39 | /// Destructor 40 | virtual ~AttachmentService() {} 41 | 42 | /// @return string - the descriptive name of the service 43 | const std::string name() const override { return "AttachmentService"; } 44 | 45 | protected: 46 | /// Called by tick() by default. Override in subclasses 47 | /// @return false if it wants to stop. 48 | bool doTick() override; 49 | 50 | protected: 51 | void reattachSweep(db::Connection& connection, 52 | const iota::POWProvider& powProvider, 53 | const db::Sweep& sweep); 54 | 55 | void promoteSweep(db::Connection& connection, 56 | const iota::POWProvider& powProvider, 57 | const db::Sweep& sweep, 58 | const common::crypto::Hash& tailHash); 59 | 60 | bool checkForUserReattachment(db::Connection& connection, 61 | const db::Sweep& sweep, 62 | const std::vector& knownTails); 63 | 64 | bool checkSweepTailsForConfirmation(db::Connection& connection, 65 | const db::Sweep& sweep, 66 | const std::vector& tails); 67 | 68 | protected: 69 | /// an cppclient::IotaAPI compliant API provider 70 | const std::shared_ptr _api; 71 | }; 72 | 73 | } // namespace service 74 | } // namespace hub 75 | 76 | #endif // HUB_SERVICE_ATTACHMENT_SERVICE_H_ 77 | -------------------------------------------------------------------------------- /hub/service/scheduled_service.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/service/scheduled_service.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | namespace hub { 19 | namespace service { 20 | 21 | void ScheduledService::start() { 22 | if (_interval == std::chrono::milliseconds::zero()) { 23 | LOG(INFO) << " Not starting " << name() << " because it's disabled."; 24 | return; 25 | } 26 | 27 | Service::start(); 28 | 29 | _timer = std::make_unique(_service); 30 | 31 | _timer->expires_from_now(_interval); 32 | _timer->async_wait(boost::bind(&ScheduledService::tick, this)); 33 | } 34 | 35 | void ScheduledService::tick() { 36 | VLOG(3) << name() << "::tick()"; 37 | 38 | auto ret = doTick(); 39 | 40 | if (ret) { 41 | _timer->expires_from_now(_interval); 42 | _timer->async_wait(boost::bind(&ScheduledService::tick, this)); 43 | } 44 | } 45 | 46 | void ScheduledService::stop() { 47 | if (_interval == std::chrono::milliseconds::zero()) { 48 | LOG(INFO) << " Not stopping " << name() << " because it's disabled."; 49 | return; 50 | } 51 | 52 | _timer = nullptr; 53 | Service::stop(); 54 | } 55 | 56 | } // namespace service 57 | } // namespace hub 58 | -------------------------------------------------------------------------------- /hub/service/scheduled_service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVICE_SCHEDULED_SERVICE_H_ 9 | #define HUB_SERVICE_SCHEDULED_SERVICE_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "hub/service/service.h" 17 | 18 | namespace hub { 19 | namespace service { 20 | 21 | /// ScheduledService abstract class. This is the base class for all scheduled 22 | /// services. Each concrete subclass is responsible for implementing their 23 | /// respective behaviour in the protected onTick() method 24 | class ScheduledService : public Service { 25 | public: 26 | ScheduledService() = delete; 27 | 28 | /// constructor 29 | /// @param[in] interval - the tick interval in milliseconds 30 | explicit ScheduledService(std::chrono::milliseconds interval) 31 | : _interval(interval) {} 32 | 33 | /// Start the service 34 | void start() override; 35 | /// Stop the service 36 | void stop() override; 37 | /// Invoked at each tick occuring at interval milliseconds 38 | void tick(); 39 | 40 | protected: 41 | /// Called by tick() by default 42 | /// @return false if it wants to stop. 43 | virtual bool doTick() = 0; 44 | 45 | protected: 46 | using Timer = boost::asio::basic_waitable_timer; 47 | 48 | const std::chrono::milliseconds _interval; 49 | std::unique_ptr _timer; 50 | }; 51 | 52 | } // namespace service 53 | 54 | } // namespace hub 55 | 56 | #endif // HUB_SERVICE_SCHEDULED_SERVICE_H_ 57 | -------------------------------------------------------------------------------- /hub/service/service.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "hub/service/service.h" 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace hub { 16 | namespace service { 17 | 18 | void Service::start() { 19 | if (_thread) { 20 | throw std::runtime_error{name() + "::start called but already running."}; 21 | } 22 | 23 | _work = std::make_unique(_service); 24 | _thread = std::make_unique( 25 | boost::bind(&boost::asio::io_service::run, &_service)); 26 | 27 | onStart(); 28 | } 29 | 30 | void Service::stop() { 31 | if (!_thread) { 32 | throw std::runtime_error{name() + "::stop called but was not running."}; 33 | } 34 | 35 | onStop(); 36 | 37 | _work = nullptr; 38 | _service.stop(); 39 | _thread->join(); 40 | _thread = nullptr; 41 | } 42 | 43 | } // namespace service 44 | } // namespace hub 45 | -------------------------------------------------------------------------------- /hub/service/service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVICE_SERVICE_H_ 9 | #define HUB_SERVICE_SERVICE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace hub { 19 | namespace service { 20 | 21 | /// Service abstract class. This is the base class for all services 22 | /// Each concrete subclass is responsible for implementing their 23 | /// respective behaviour 24 | class Service { 25 | public: 26 | /// constructor 27 | Service() {} 28 | 29 | /// Start the service 30 | virtual void start(); 31 | /// Stop the service 32 | virtual void stop(); 33 | /// @return bool - true if the service is currently running, false otherwise 34 | virtual bool isRunning() { return _thread != nullptr; } 35 | 36 | /// @return string - the descriptive name of the service 37 | virtual const std::string name() const = 0; 38 | 39 | protected: 40 | /// Called immediately after starting the service 41 | virtual void onStart() {} 42 | /// Called immediately before stopping the service 43 | virtual void onStop() {} 44 | 45 | // Order of destruction matters for the below 46 | private: 47 | std::unique_ptr _thread; 48 | 49 | protected: 50 | boost::asio::io_service _service; 51 | boost::asio::io_service::strand _strand{_service}; 52 | 53 | private: 54 | std::unique_ptr _work; 55 | }; 56 | 57 | } // namespace service 58 | 59 | } // namespace hub 60 | 61 | #endif // HUB_SERVICE_SERVICE_H_ 62 | -------------------------------------------------------------------------------- /hub/service/sweep_service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVICE_SWEEP_SERVICE_H_ 9 | #define HUB_SERVICE_SWEEP_SERVICE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "common/crypto/types.h" 19 | #include "cppclient/api.h" 20 | #include "hub/db/types.h" 21 | #include "hub/service/scheduled_service.h" 22 | 23 | namespace hub { 24 | namespace service { 25 | 26 | /// SweepService class. 27 | /// The sweep service is responsible for consolidating all the deposit and 28 | /// widthdrawal transactions into hub addresses 29 | class SweepService : public ScheduledService { 30 | public: 31 | /// constructor 32 | /// @param[in] api - an cppclient::IotaAPI compliant API provider 33 | /// @param[in] interval - the tick interval in milliseconds 34 | explicit SweepService(std::shared_ptr api, 35 | std::chrono::milliseconds interval) 36 | : ScheduledService(interval), _api(std::move(api)) {} 37 | 38 | /// Destructor 39 | virtual ~SweepService() {} 40 | 41 | /// @return string - the descriptive name of the service 42 | const std::string name() const override { return "SweepService"; } 43 | 44 | /// Creates a new hub address to which funds that remain after a transfer 45 | /// can be moved. 46 | /// @param[in] remainder 47 | /// @return a db::TransferOutput structure containing 48 | /// - the new hub address 49 | /// - the id of the new hub address 50 | /// - the remainder 51 | db::TransferOutput getHubOutput(uint64_t remainder); 52 | 53 | protected: 54 | /// Called by tick() by default. Override in subclasses 55 | /// @return false if it wants to stop. 56 | bool doTick() override; 57 | /// an cppclient::IotaAPI compliant API provider 58 | const std::shared_ptr _api; 59 | 60 | private: 61 | void backupUnsweptHubAddresses() const; 62 | }; 63 | 64 | } // namespace service 65 | } // namespace hub 66 | 67 | #endif // HUB_SERVICE_SWEEP_SERVICE_H_ 68 | -------------------------------------------------------------------------------- /hub/service/tests/scheduled_service.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include "hub/service/scheduled_service.h" 10 | 11 | using namespace testing; 12 | 13 | using namespace hub; 14 | using namespace hub::service; 15 | 16 | namespace { 17 | 18 | class ScheduledServiceTest : public ::testing::Test {}; 19 | 20 | class MockService : public ScheduledService { 21 | public: 22 | using ScheduledService::ScheduledService; 23 | 24 | const std::string name() const override { return "MockService"; } 25 | MOCK_METHOD0(doTick, bool()); 26 | }; 27 | 28 | TEST_F(ScheduledServiceTest, SchedulingWorks) { 29 | using namespace std::chrono_literals; 30 | auto timeout = 100ms; 31 | 32 | MockService service(timeout); 33 | 34 | service.start(); 35 | EXPECT_CALL(service, doTick()).Times(1).WillOnce(Return(false)); 36 | 37 | std::this_thread::sleep_for(1.5 * timeout); 38 | 39 | service.stop(); 40 | } 41 | 42 | }; // namespace 43 | -------------------------------------------------------------------------------- /hub/service/user_address_monitor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef HUB_SERVICE_USER_ADDRESS_MONITOR_H_ 9 | #define HUB_SERVICE_USER_ADDRESS_MONITOR_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "cppclient/api.h" 20 | #include "hub/service/address_monitor.h" 21 | 22 | namespace hub { 23 | namespace service { 24 | 25 | /// UserAddressMonitor class. 26 | /// The user address monitor service is responsible for monitoring changes in 27 | /// user addresses in the local database. 28 | class UserAddressMonitor : public AddressMonitor { 29 | public: 30 | using AddressMonitor::AddressMonitor; 31 | 32 | /// constructor 33 | /// @param[in] api - an cppclient::IotaAPI compliant API provider 34 | /// @param[in] interval - the tick interval, in milliseconds, 35 | /// @param[in] fetchTransactionMessage - Should service fetch transaction's 36 | /// message 37 | explicit UserAddressMonitor(std::shared_ptr api, 38 | std::chrono::milliseconds interval, 39 | bool fetchTransactionMessage) 40 | : AddressMonitor(std::move(api), interval), 41 | _fetchTransactionMessage(fetchTransactionMessage) {} 42 | 43 | std::vector> monitoredAddresses() override; 44 | /// Process addresses that have changes 45 | /// @param[in] changed - a list of AddressMonitor::BalanceChange structures 46 | /// @return bool - true if successful 47 | bool onBalancesChanged( 48 | const std::vector& changed) override; 49 | 50 | std::unordered_map initialBalances( 51 | std::vector ids) override; 52 | 53 | /// @return string - the descriptive name of the service 54 | const std::string name() const override { return "UserAddressMonitor"; } 55 | 56 | protected: 57 | /// Check that the balance from the tangle is not less than the 58 | /// balance held in the database for the local address 59 | /// @param[in] address - the tangle address for which to check the balance 60 | /// @param[in] addressId - the database id of the local address 61 | /// @return bool - true if balance valid for this address 62 | bool validateBalanceIsConsistent(const std::string& address, 63 | uint64_t addressId); 64 | 65 | private: 66 | bool _fetchTransactionMessage; 67 | }; 68 | 69 | } // namespace service 70 | 71 | } // namespace hub 72 | 73 | #endif // HUB_SERVICE_USER_ADDRESS_MONITOR_H_ 74 | -------------------------------------------------------------------------------- /hub/tests/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "tests", 3 | srcs = ["runner.cc"], 4 | hdrs = ["runner.h"], 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//common/crypto:argon2_provider", 8 | "//common/stats", 9 | "//hub/db", 10 | "@com_github_google_glog//:glog", 11 | "@com_google_googletest//:gtest", 12 | ], 13 | ) 14 | -------------------------------------------------------------------------------- /hub/tests/runner.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #include "hub/tests/runner.h" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "hub/db/db.h" 12 | 13 | int main(int argc, char** argv) { 14 | google::InstallFailureSignalHandler(); 15 | google::InitGoogleLogging("commands-tests"); 16 | testing::InitGoogleMock(&argc, argv); 17 | gflags::ParseCommandLineFlags(&argc, &argv, true); 18 | 19 | return RUN_ALL_TESTS(); 20 | } 21 | -------------------------------------------------------------------------------- /hub/tests/runner.h: -------------------------------------------------------------------------------- 1 | // Copyright 2018 IOTA Foundation 2 | 3 | #ifndef HUB_TESTS_RUNNER_H_ 4 | #define HUB_TESTS_RUNNER_H_ 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include "common/crypto/argon2_provider.h" 12 | #include "common/crypto/manager.h" 13 | #include "common/crypto/types.h" 14 | #include "common/stats/session.h" 15 | #include "hub/db/db.h" 16 | 17 | namespace hub { 18 | class Test : public ::testing::Test { 19 | public: 20 | virtual void SetUp() { 21 | common::crypto::CryptoManager::get().setProvider( 22 | std::make_unique("abcdefghij")); 23 | 24 | db::Config config; 25 | 26 | using std::string_literals::operator""s; 27 | 28 | config.type = "sqlite3"; 29 | config.database = 30 | "file:"s + common::crypto::UUID().str() + "?mode=memory&cache=shared"s; 31 | 32 | std::replace(config.database.begin(), config.database.end(), '+', 'X'); 33 | std::replace(config.database.begin(), config.database.end(), '/', 'Y'); 34 | 35 | auto& db = hub::db::DBManager::get(); 36 | db.setConnectionConfig(config); 37 | db.loadSchema(); 38 | 39 | _session = std::make_shared(); 40 | } 41 | 42 | virtual void TearDown() { 43 | auto& db = hub::db::DBManager::get(); 44 | db.resetConnection(); 45 | _session = nullptr; 46 | } 47 | 48 | std::shared_ptr session() { return _session; } 49 | 50 | private: 51 | std::shared_ptr _session; 52 | }; 53 | 54 | } // namespace hub 55 | #endif // HUB_TESTS_RUNNER_H_ 56 | -------------------------------------------------------------------------------- /proto/BUILD: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | load("@com_github_grpc_grpc//bazel:cc_grpc_library.bzl", "cc_grpc_library") 4 | 5 | proto_library( 6 | name = "messages_proto", 7 | srcs = ["messages.proto"], 8 | ) 9 | 10 | cc_grpc_library( 11 | name = "messages_proto_cc", 12 | srcs = ["messages.proto"], 13 | proto_only = True, 14 | well_known_protos = False, 15 | deps = [], 16 | ) 17 | 18 | cc_grpc_library( 19 | name = "hub_grpc_cc", 20 | srcs = ["hub.proto"], 21 | generate_mocks = True, 22 | proto_only = False, 23 | well_known_protos = False, 24 | deps = [":messages_proto_cc"], 25 | ) 26 | 27 | proto_library( 28 | name = "signing_server_messages_proto", 29 | srcs = ["signing_server_messages.proto"], 30 | ) 31 | 32 | cc_grpc_library( 33 | name = "signing_server_messages_proto_cc", 34 | srcs = ["signing_server_messages.proto"], 35 | proto_only = True, 36 | well_known_protos = False, 37 | deps = [], 38 | ) 39 | 40 | cc_grpc_library( 41 | name = "signing_server_grpc_cc", 42 | srcs = ["signing_server.proto"], 43 | proto_only = False, 44 | well_known_protos = False, 45 | deps = [":signing_server_messages_proto_cc"], 46 | ) 47 | -------------------------------------------------------------------------------- /proto/signing_server.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "org.iota.signing_server"; 4 | 5 | package signing.rpc; 6 | import "proto/signing_server_messages.proto"; 7 | 8 | service SigningServer { 9 | // Gets the address for the UUID 10 | rpc GetAddressForUUID (GetAddressForUUIDRequest) returns (GetAddressForUUIDReply); 11 | // Gets the signature for the UUID 12 | rpc GetSignatureForUUID (GetSignatureForUUIDRequest) returns (GetSignatureForUUIDReply); 13 | // Gets the security level of the provider 14 | rpc GetSecurityLevel (GetSecurityLevelRequest) returns (GetSecurityLevelReply); 15 | //Get the seed associated with the given address - this function can be used for backing up the seed 16 | rpc GetSeedForUUID (GetSeedForUUIDRequest) returns (GetSeedForUUIDReply); 17 | } -------------------------------------------------------------------------------- /proto/signing_server_messages.proto: -------------------------------------------------------------------------------- 1 | /* 2 | * Crypto Provider related messages. 3 | */ 4 | 5 | syntax = "proto3"; 6 | 7 | option java_package = "org.iota.signing_server"; 8 | 9 | package signing.rpc; 10 | 11 | enum ErrorCode { 12 | // Unused. 13 | EC_UNKNOWN = 0; 14 | } 15 | 16 | /* 17 | * The generic Error that will be used to return an error code on, e.g. Status::CANCELLED. 18 | * 19 | * The error will be serialised and stored in the Status' detail field. 20 | */ 21 | message Error { 22 | ErrorCode code = 1; 23 | } 24 | 25 | /* 26 | * Request for getting address 27 | */ 28 | message GetAddressForUUIDRequest { 29 | string uuid = 1; 30 | } 31 | 32 | /* 33 | * Reply for getting address 34 | */ 35 | message GetAddressForUUIDReply { 36 | string address = 1; 37 | } 38 | 39 | /* 40 | * Request for getting signature 41 | */ 42 | message GetSignatureForUUIDRequest { 43 | string uuid = 1; 44 | string bundleHash = 2; 45 | } 46 | 47 | /* 48 | * Reply for getting signature 49 | */ 50 | message GetSignatureForUUIDReply { 51 | string signature = 1; 52 | } 53 | 54 | /* 55 | * Request for getting security level 56 | */ 57 | message GetSecurityLevelRequest { 58 | string uuid = 1; 59 | } 60 | /* 61 | * Reply for getting security level 62 | */ 63 | message GetSecurityLevelReply { 64 | uint32 securityLevel = 1; 65 | } 66 | 67 | 68 | message GetSeedForUUIDRequest{ 69 | //The uuid 70 | string uuid = 1; 71 | } 72 | 73 | message GetSeedForUUIDReply{ 74 | //The seed 75 | string seed = 1; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyparsing 2 | -------------------------------------------------------------------------------- /schema/BUILD: -------------------------------------------------------------------------------- 1 | load( 2 | "@rules_python//python:python.bzl", 3 | "py_binary", 4 | ) 5 | load( 6 | "@py_deps//:requirements.bzl", 7 | "requirement", 8 | ) 9 | 10 | py_binary( 11 | name = "ddl2cpp", 12 | srcs = ["ddl2cpp.py"], 13 | deps = [ 14 | requirement("pyparsing"), 15 | ], 16 | ) 17 | 18 | genrule( 19 | name = "headers", 20 | srcs = [ 21 | "schema.sql", 22 | ], 23 | outs = ["schema.h"], 24 | cmd = """ 25 | $(location //schema:ddl2cpp) $(location schema.sql) schema hub::db::sql 26 | cp schema.h $@ 27 | """, 28 | tools = [":ddl2cpp"], 29 | ) 30 | 31 | cc_library( 32 | name = "schema", 33 | hdrs = [":headers"], 34 | data = [ 35 | "schema.sql", 36 | "triggers.mariadb.sql", 37 | "triggers.sqlite3.sql", 38 | ], 39 | visibility = ["//visibility:public"], 40 | ) 41 | -------------------------------------------------------------------------------- /schema/delta.mariadb.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE user_address_balance ADD COLUMN IF NOT EXISTS message TEXT(2187) DEFAULT NULL; -------------------------------------------------------------------------------- /schema/delta.sqlite3.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE user_address_balance ADD COLUMN message TEXT(2187) DEFAULT NULL; -------------------------------------------------------------------------------- /schema/triggers.mariadb.sql: -------------------------------------------------------------------------------- 1 | DELIMITER $$ 2 | 3 | CREATE TRIGGER hub_address_balance_insert 4 | AFTER INSERT ON hub_address_balance 5 | FOR EACH ROW 6 | BEGIN 7 | UPDATE hub_address 8 | SET balance = ( 9 | SELECT SUM(amount) FROM hub_address_balance 10 | WHERE hub_address = NEW.hub_address 11 | ) 12 | WHERE id = NEW.hub_address; END $$ 13 | 14 | CREATE TRIGGER user_address_balance_insert 15 | AFTER INSERT ON user_address_balance 16 | FOR EACH ROW 17 | BEGIN 18 | UPDATE user_address 19 | SET balance = ( 20 | SELECT SUM(amount) FROM user_address_balance WHERE user_address = NEW.user_address 21 | ) 22 | WHERE id = NEW.user_address; END $$ 23 | 24 | CREATE TRIGGER user_account_balance_insert 25 | AFTER INSERT ON user_account_balance 26 | FOR EACH ROW 27 | BEGIN 28 | UPDATE user_account 29 | SET balance = ( 30 | SELECT SUM(amount) FROM user_account_balance WHERE user_id = NEW.user_id 31 | ) WHERE id = NEW.user_id; END $$ 32 | 33 | CREATE TRIGGER sweep_tails_update 34 | AFTER UPDATE 35 | ON sweep_tails FOR EACH ROW 36 | BEGIN 37 | UPDATE sweep SET confirmed = NEW.confirmed 38 | WHERE sweep.id = NEW.sweep AND sweep.confirmed = 0; END $$ 39 | 40 | DELIMITER ; 41 | -------------------------------------------------------------------------------- /schema/triggers.sqlite3.sql: -------------------------------------------------------------------------------- 1 | CREATE TRIGGER hub_address_balance_insert 2 | AFTER INSERT ON hub_address_balance 3 | FOR EACH ROW 4 | BEGIN 5 | UPDATE hub_address 6 | SET balance = ( 7 | SELECT SUM(amount) FROM hub_address_balance 8 | WHERE hub_address = NEW.hub_address 9 | ) 10 | WHERE id = NEW.hub_address; END; 11 | 12 | CREATE TRIGGER user_address_balance_insert 13 | AFTER INSERT ON user_address_balance 14 | FOR EACH ROW 15 | BEGIN 16 | UPDATE user_address 17 | SET balance = ( 18 | SELECT SUM(amount) FROM user_address_balance WHERE user_address = NEW.user_address 19 | ) 20 | WHERE id = NEW.user_address; END; 21 | 22 | 23 | CREATE TRIGGER user_account_balance_insert 24 | AFTER INSERT ON user_account_balance 25 | FOR EACH ROW 26 | BEGIN 27 | UPDATE user_account 28 | SET balance = ( 29 | SELECT SUM(amount) FROM user_account_balance WHERE user_id = NEW.user_id 30 | ) WHERE id = NEW.user_id; END; 31 | 32 | CREATE TRIGGER sweep_tails_update 33 | AFTER UPDATE 34 | ON sweep_tails FOR EACH ROW 35 | BEGIN 36 | UPDATE sweep SET confirmed = NEW.confirmed 37 | WHERE sweep.id = NEW.sweep AND sweep.confirmed = 0; END; 38 | -------------------------------------------------------------------------------- /signing_server/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "server", 3 | srcs = [ 4 | "grpc.cc", 5 | "server.cc", 6 | ], 7 | hdrs = [ 8 | "grpc.h", 9 | "server.h", 10 | ], 11 | visibility = ["//visibility:public"], 12 | deps = [ 13 | "//common", 14 | "//common/crypto:argon2_provider", 15 | "//signing_server/commands", 16 | "@com_github_gflags_gflags//:gflags", 17 | "@com_github_google_glog//:glog", 18 | ], 19 | ) 20 | 21 | cc_binary( 22 | name = "signing_server", 23 | srcs = ["main.cc"], 24 | visibility = ["//visibility:public"], 25 | deps = [ 26 | ":server", 27 | "@com_github_gflags_gflags//:gflags", 28 | "@com_github_google_glog//:glog", 29 | ], 30 | ) 31 | -------------------------------------------------------------------------------- /signing_server/commands/BUILD: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "commands", 3 | srcs = glob( 4 | [ 5 | "**/*.cc", 6 | "*.h", 7 | ], 8 | exclude = ["tests/**/*"], 9 | ), 10 | hdrs = glob( 11 | ["*.h"], 12 | exclude = ["tests/**/*"], 13 | ), 14 | visibility = ["//visibility:public"], 15 | deps = [ 16 | "//common", 17 | "//common/crypto:argon2_provider", 18 | "//proto:signing_server_grpc_cc", 19 | ], 20 | ) 21 | -------------------------------------------------------------------------------- /signing_server/commands/get_address_for_uuid.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | 9 | #include "get_address_for_uuid.h" 10 | 11 | #include "common/crypto/manager.h" 12 | #include "proto/signing_server.pb.h" 13 | #include "proto/signing_server_messages.pb.h" 14 | 15 | #include "common/crypto/types.h" 16 | #include "proto/messages.pb.h" 17 | #include "signing_server/commands/helper.h" 18 | 19 | namespace signing { 20 | namespace cmd { 21 | 22 | common::cmd::Error GetAddressForUUID::doProcess( 23 | const signing::rpc::GetAddressForUUIDRequest* request, 24 | signing::rpc::GetAddressForUUIDReply* response) noexcept { 25 | try { 26 | LOG(INFO) << session() << " GetAddressForUUID: " << request->uuid(); 27 | 28 | common::crypto::UUID uuid(request->uuid()); 29 | auto address = common::crypto::CryptoManager::get() 30 | .provider() 31 | .getAddressForUUID(uuid) 32 | .value(); 33 | response->set_address(address.str()); 34 | } catch (const std::runtime_error& ex) { 35 | LOG(ERROR) << session() << "Failed: " << ex.what(); 36 | 37 | return common::cmd::UNKNOWN_ERROR; 38 | } 39 | 40 | return common::cmd::OK; 41 | } 42 | 43 | } // namespace cmd 44 | 45 | } // namespace signing 46 | -------------------------------------------------------------------------------- /signing_server/commands/get_address_for_uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_COMMANDS_GET_ADDRESS_FOR_UUID_H_ 9 | #define SIGNING_SERVER_COMMANDS_GET_ADDRESS_FOR_UUID_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace signing { 16 | namespace rpc { 17 | class GetAddressForUUIDRequest; 18 | class GetAddressForUUIDReply; 19 | } // namespace rpc 20 | 21 | namespace cmd { 22 | 23 | /// Gets information on an address 24 | /// @param[in] common::rpc::GetAddressForUUIDRequest 25 | /// @param[in] common::rpc::GetAddressForUUIDReply 26 | class GetAddressForUUID 27 | : public common::Command { 29 | public: 30 | using common::Command::Command; 32 | 33 | static const std::string name() { return "GetAddressForUUID"; } 34 | 35 | common::cmd::Error doProcess( 36 | const signing::rpc::GetAddressForUUIDRequest* request, 37 | signing::rpc::GetAddressForUUIDReply* response) noexcept override; 38 | 39 | boost::property_tree::ptree doProcess( 40 | const boost::property_tree::ptree& request) noexcept override {return boost::property_tree::ptree();}; 41 | }; 42 | } // namespace cmd 43 | } // namespace signing 44 | 45 | #endif // SIGNING_SERVER_COMMANDS_GET_ADDRESS_FOR_UUID_H_ 46 | -------------------------------------------------------------------------------- /signing_server/commands/get_security_level.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "get_security_level.h" 9 | 10 | #include "common/crypto/manager.h" 11 | #include "proto/signing_server.pb.h" 12 | #include "proto/signing_server_messages.pb.h" 13 | 14 | #include "common/crypto/types.h" 15 | 16 | namespace signing { 17 | namespace cmd { 18 | 19 | common::cmd::Error GetSecurityLevel::doProcess( 20 | const signing::rpc::GetSecurityLevelRequest* request, 21 | signing::rpc::GetSecurityLevelReply* response) noexcept { 22 | try { 23 | LOG(INFO) << session() << " GetSecurityLevel for uuid: " << request->uuid(); 24 | 25 | auto security = common::crypto::CryptoManager::get() 26 | .provider() 27 | .securityLevel(common::crypto::UUID(request->uuid())) 28 | .value(); 29 | response->set_securitylevel(security); 30 | } catch (const std::runtime_error& ex) { 31 | LOG(ERROR) << session() << "Failed: " << ex.what(); 32 | 33 | return common::cmd::UNKNOWN_ERROR; 34 | } 35 | 36 | return common::cmd::OK; 37 | } 38 | 39 | } // namespace cmd 40 | 41 | } // namespace signing 42 | -------------------------------------------------------------------------------- /signing_server/commands/get_security_level.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_COMMANDS_GET_SECURITY_LEVEL_H_ 9 | #define SIGNING_SERVER_COMMANDS_GET_SECURITY_LEVEL_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace signing { 16 | namespace rpc { 17 | class GetSecurityLevelRequest; 18 | class GetSecurityLevelReply; 19 | } // namespace rpc 20 | 21 | namespace cmd { 22 | 23 | /// Gets information on an signature 24 | /// @param[in] common::rpc::GetSignatureForUUIDRequest 25 | /// @param[in] common::rpc::GetSignatureForUUIDReply 26 | class GetSecurityLevel 27 | : public common::Command { 29 | public: 30 | using common::Command::Command; 32 | 33 | static const std::string name() { return "GetSecurityLevel"; } 34 | 35 | common::cmd::Error doProcess( 36 | const signing::rpc::GetSecurityLevelRequest* request, 37 | signing::rpc::GetSecurityLevelReply* response) noexcept override; 38 | 39 | boost::property_tree::ptree doProcess( 40 | const boost::property_tree::ptree& request) noexcept override {return boost::property_tree::ptree();}; 41 | }; 42 | } // namespace cmd 43 | } // namespace signing 44 | 45 | #endif // SIGNING_SERVER_COMMANDS_GET_SECURITY_LEVEL_H_ 46 | -------------------------------------------------------------------------------- /signing_server/commands/get_seed_for_uuid.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "get_seed_for_uuid.h" 9 | 10 | #include "common/crypto/manager.h" 11 | #include "proto/signing_server.pb.h" 12 | #include "proto/signing_server_messages.pb.h" 13 | 14 | #include "common/crypto/types.h" 15 | #include "proto/messages.pb.h" 16 | #include "signing_server/commands/helper.h" 17 | 18 | namespace signing { 19 | namespace cmd { 20 | 21 | common::cmd::Error GetSeedForUUID::doProcess( 22 | const signing::rpc::GetSeedForUUIDRequest* request, 23 | signing::rpc::GetSeedForUUIDReply* response) noexcept { 24 | try { 25 | LOG(INFO) << session() << " GetSeedForUUID: " << request->uuid(); 26 | 27 | common::crypto::UUID uuid(request->uuid()); 28 | auto seed = common::crypto::CryptoManager::get() 29 | .provider() 30 | .getSeedFromUUID(uuid); 31 | 32 | response->set_seed(seed); 33 | } catch (const std::runtime_error& ex) { 34 | LOG(ERROR) << session() << "Failed: " << ex.what(); 35 | 36 | return common::cmd::UNKNOWN_ERROR; 37 | } 38 | 39 | return common::cmd::OK; 40 | } 41 | 42 | } // namespace cmd 43 | 44 | } // namespace signing 45 | -------------------------------------------------------------------------------- /signing_server/commands/get_seed_for_uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_COMMANDS_GET_SEED_FOR_UUID_H_ 9 | #define SIGNING_SERVER_COMMANDS_GET_SEED_FOR_UUID_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace signing { 16 | namespace rpc { 17 | class GetSeedForUUIDRequest; 18 | class GetSeedForUUIDReply; 19 | } // namespace rpc 20 | 21 | namespace cmd { 22 | 23 | /// Gets information on an uuid 24 | /// @param[in] common::rpc::GetSeedForUUIDRequest 25 | /// @param[in] common::rpc::GetSeedForUUIDReply 26 | class GetSeedForUUID 27 | : public common::Command { 29 | public: 30 | using common::Command::Command; 32 | 33 | static const std::string name() { return "GetSeedForUUID"; } 34 | 35 | common::cmd::Error doProcess( 36 | const signing::rpc::GetSeedForUUIDRequest* request, 37 | signing::rpc::GetSeedForUUIDReply* response) noexcept override; 38 | 39 | boost::property_tree::ptree doProcess( 40 | const boost::property_tree::ptree& request) noexcept override {return boost::property_tree::ptree();}; 41 | }; 42 | } // namespace cmd 43 | } // namespace signing 44 | 45 | #endif // SIGNING_SERVER_COMMANDS_GET_SEED_FOR_UUID_H_ 46 | -------------------------------------------------------------------------------- /signing_server/commands/get_signature_for_uuid.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include "get_signature_for_uuid.h" 9 | 10 | #include "common/crypto/manager.h" 11 | #include "proto/signing_server.pb.h" 12 | #include "proto/signing_server_messages.pb.h" 13 | 14 | #include "common/crypto/types.h" 15 | 16 | namespace signing { 17 | namespace cmd { 18 | 19 | common::cmd::Error GetSignatureForUUID::doProcess( 20 | const signing::rpc::GetSignatureForUUIDRequest* request, 21 | signing::rpc::GetSignatureForUUIDReply* response) noexcept { 22 | try { 23 | LOG(INFO) << session() << " GetSignatureForUUID - uuid: " << request->uuid() 24 | << " bundle hash: " << request->bundlehash(); 25 | 26 | common::crypto::UUID uuid(request->uuid()); 27 | common::crypto::Hash bundleHash(request->bundlehash()); 28 | 29 | response->set_signature(common::crypto::CryptoManager::get() 30 | .provider() 31 | .forceGetSignatureForUUID(uuid, bundleHash) 32 | .value()); 33 | } catch (const std::runtime_error& ex) { 34 | LOG(ERROR) << session() << "Failed: " << ex.what(); 35 | 36 | return common::cmd::UNKNOWN_ERROR; 37 | } 38 | 39 | return common::cmd::OK; 40 | } 41 | 42 | } // namespace cmd 43 | 44 | } // namespace signing 45 | 46 | // 47 | // Created by tsvi on 6/27/18. 48 | // 49 | -------------------------------------------------------------------------------- /signing_server/commands/get_signature_for_uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_COMMANDS_GET_SIGNATURE_FOR_UUID_H_ 9 | #define SIGNING_SERVER_COMMANDS_GET_SIGNATURE_FOR_UUID_H_ 10 | 11 | #include 12 | 13 | #include "common/commands/command.h" 14 | 15 | namespace signing { 16 | namespace rpc { 17 | class GetSignatureForUUIDRequest; 18 | class GetSignatureForUUIDReply; 19 | } // namespace rpc 20 | 21 | namespace cmd { 22 | 23 | /// Gets information on an signature 24 | /// @param[in] common::rpc::GetSignatureForUUIDRequest 25 | /// @param[in] common::rpc::GetSignatureForUUIDReply 26 | class GetSignatureForUUID 27 | : public common::Command { 29 | public: 30 | using common::Command::Command; 32 | 33 | static const std::string name() { return "GetSignatureForUUID"; } 34 | 35 | common::cmd::Error doProcess( 36 | const signing::rpc::GetSignatureForUUIDRequest* request, 37 | signing::rpc::GetSignatureForUUIDReply* response) noexcept override; 38 | 39 | boost::property_tree::ptree doProcess( 40 | const boost::property_tree::ptree& request) noexcept override {return boost::property_tree::ptree();}; 41 | }; 42 | } // namespace cmd 43 | } // namespace signing 44 | 45 | #endif // SIGNING_SERVER_COMMANDS_GET_SIGNATURE_FOR_UUID_H_ 46 | -------------------------------------------------------------------------------- /signing_server/commands/helper.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "proto/signing_server_messages.pb.h" 12 | #include "signing_server/commands/helper.h" 13 | 14 | namespace signing { 15 | 16 | namespace cmd { 17 | std::string errorToString(const signing::rpc::ErrorCode& e) { 18 | std::ostringstream ss; 19 | signing::rpc::Error error; 20 | 21 | error.set_code(e); 22 | error.SerializeToOstream(&ss); 23 | 24 | return ss.str(); 25 | } 26 | } // namespace cmd 27 | } // namespace signing 28 | -------------------------------------------------------------------------------- /signing_server/commands/helper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_COMMANDS_HELPER_H_ 9 | #define SIGNING_SERVER_COMMANDS_HELPER_H_ 10 | 11 | #include 12 | 13 | #include "proto/signing_server.pb.h" 14 | 15 | namespace signing { 16 | 17 | namespace cmd { 18 | std::string errorToString(const signing::rpc::ErrorCode& e); 19 | } 20 | } // namespace signing 21 | 22 | #endif // SIGNING_SERVER_COMMANDS_HELPER_H_ 23 | -------------------------------------------------------------------------------- /signing_server/grpc.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "signing_server/grpc.h" 12 | #include "common/crypto/provider_base.h" 13 | #include "common/stats/session.h" 14 | #include "signing_server/commands/get_address_for_uuid.h" 15 | #include "signing_server/commands/get_security_level.h" 16 | #include "signing_server/commands/get_seed_for_uuid.h" 17 | #include "signing_server/commands/get_signature_for_uuid.h" 18 | 19 | namespace signing { 20 | namespace rpc { 21 | 22 | // Gets the address for the UUID 23 | grpc::Status SigningServerImpl::GetAddressForUUID( 24 | ::grpc::ServerContext* context, const GetAddressForUUIDRequest* request, 25 | GetAddressForUUIDReply* response) { 26 | auto clientSession = std::make_shared(); 27 | cmd::GetAddressForUUID cmd(clientSession); 28 | return common::cmd::errorToGrpcError(cmd.process(request, response)); 29 | } 30 | // Gets the signature for the UUID 31 | grpc::Status SigningServerImpl::GetSignatureForUUID( 32 | ::grpc::ServerContext* context, const GetSignatureForUUIDRequest* request, 33 | GetSignatureForUUIDReply* response) { 34 | auto clientSession = std::make_shared(); 35 | cmd::GetSignatureForUUID cmd(clientSession); 36 | return common::cmd::errorToGrpcError(cmd.process(request, response)); 37 | } 38 | // Gets the security level of the provider 39 | grpc::Status SigningServerImpl::GetSecurityLevel( 40 | ::grpc::ServerContext* context, const GetSecurityLevelRequest* request, 41 | GetSecurityLevelReply* response) { 42 | auto clientSession = std::make_shared(); 43 | cmd::GetSecurityLevel cmd(clientSession); 44 | return common::cmd::errorToGrpcError(cmd.process(request, response)); 45 | } 46 | 47 | grpc::Status SigningServerImpl::GetSeedForUUID( 48 | grpc::ServerContext* context, 49 | const GetSeedForUUIDRequest* request, 50 | GetSeedForUUIDReply* response){ 51 | auto clientSession = std::make_shared(); 52 | cmd::GetSeedForUUID cmd(clientSession); 53 | return common::cmd::errorToGrpcError(cmd.process(request, response)); 54 | } 55 | 56 | } // namespace rpc 57 | } // namespace signing 58 | -------------------------------------------------------------------------------- /signing_server/grpc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_GRPC_H_ 9 | #define SIGNING_SERVER_GRPC_H_ 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include "proto/signing_server.grpc.pb.h" 16 | #include "proto/signing_server.pb.h" 17 | #include "proto/signing_server_messages.pb.h" 18 | 19 | namespace signing { 20 | namespace rpc { 21 | 22 | class SigningServerImpl final : public SigningServer::Service { 23 | public: 24 | /// Constructor 25 | SigningServerImpl() {} 26 | /// Destructor 27 | ~SigningServerImpl() override {} 28 | 29 | // Gets the address for the UUID 30 | grpc::Status GetAddressForUUID(::grpc::ServerContext* context, 31 | const GetAddressForUUIDRequest* request, 32 | GetAddressForUUIDReply* response) override; 33 | // Gets the signature for the UUID 34 | grpc::Status GetSignatureForUUID(::grpc::ServerContext* context, 35 | const GetSignatureForUUIDRequest* request, 36 | GetSignatureForUUIDReply* response) override; 37 | // Gets the security level of the provider 38 | grpc::Status GetSecurityLevel(::grpc::ServerContext* context, 39 | const GetSecurityLevelRequest* request, 40 | GetSecurityLevelReply* response) override; 41 | 42 | /// Gets seed for a uuid 43 | grpc::Status GetSeedForUUID( 44 | grpc::ServerContext* context, 45 | const GetSeedForUUIDRequest* request, 46 | GetSeedForUUIDReply* response) override; 47 | }; 48 | 49 | } // namespace rpc 50 | } // namespace signing 51 | 52 | #endif // SIGNING_SERVER_GRPC_H_ -------------------------------------------------------------------------------- /signing_server/main.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include "signing_server/server.h" 12 | 13 | int main(int argc, char** argv) { 14 | google::InstallFailureSignalHandler(); 15 | 16 | auto programName = argc && argv && argc > 0 ? argv[0] : "unknown"; 17 | google::InitGoogleLogging(programName); 18 | gflags::ParseCommandLineFlags(&argc, &argv, true); 19 | 20 | LOG(INFO) << "Signing server starting up."; 21 | 22 | signing::crypto::SigningServer server; 23 | 24 | server.initialize(); 25 | server.runAndWait(); 26 | } 27 | -------------------------------------------------------------------------------- /signing_server/server.cc: -------------------------------------------------------------------------------- 1 | #include "server.h" 2 | #include "common/crypto/manager.h" 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "common/common.h" 11 | #include "common/crypto/argon2_provider.h" 12 | #include "common/crypto/manager.h" 13 | #include "common/flags.h" 14 | 15 | using grpc::Server; 16 | using grpc::ServerBuilder; 17 | using namespace common::flags; 18 | 19 | namespace signing { 20 | 21 | namespace crypto { 22 | 23 | void SigningServer::initialize() { 24 | if (common::flags::FLAGS_salt.size() <= 20) { 25 | LOG(FATAL) << "Salt must be more than 20 characters long."; 26 | } 27 | common::crypto::CryptoManager::get().setProvider( 28 | std::make_unique( 29 | common::flags::FLAGS_salt)); 30 | 31 | ServerBuilder builder; 32 | 33 | if (common::flags::FLAGS_authMode != "ssl") { 34 | LOG(FATAL) << "Remote signing_server should run only with credentials."; 35 | } 36 | 37 | builder.AddListeningPort( 38 | common::flags::FLAGS_listenAddress, 39 | makeCredentials(common::flags::FLAGS_authMode, 40 | common::flags::FLAGS_sslCert, common::flags::FLAGS_sslKey, 41 | common::flags::FLAGS_sslCA)); 42 | builder.RegisterService(&_service); 43 | 44 | _server = builder.BuildAndStart(); 45 | 46 | LOG(INFO) << "Server listening on " << common::flags::FLAGS_listenAddress; 47 | } 48 | 49 | } // namespace crypto 50 | } // namespace signing 51 | -------------------------------------------------------------------------------- /signing_server/server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 IOTA Stiftung 3 | * https://github.com/iotaledger/hub 4 | * 5 | * Refer to the LICENSE file for licensing information 6 | */ 7 | 8 | #ifndef SIGNING_SERVER_SERVER_H_ 9 | #define SIGNING_SERVER_SERVER_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | #include "common/grpc_server_base.h" 16 | #include "signing_server/grpc.h" 17 | 18 | namespace signing { 19 | 20 | namespace crypto { 21 | 22 | /// SigningServer class. 23 | /// The SigningServer holds the underlying logic which provides 24 | /// Addresses/Signature/Seed generation based on a secret "salt" argument 25 | class SigningServer : public common::GrpcServerBase { 26 | public: 27 | /// Creates and initializes the API interface. 28 | void initialize() override; 29 | 30 | private: 31 | signing::rpc::SigningServerImpl _service; 32 | }; 33 | } // namespace crypto 34 | 35 | } // namespace signing 36 | 37 | #endif // SIGNING_SERVER_SERVER_H_ 38 | -------------------------------------------------------------------------------- /third-party/cpprest/BUILD.bzl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/hub/9df503d4def3021b082ba7aaaace7a9265e2ba18/third-party/cpprest/BUILD.bzl -------------------------------------------------------------------------------- /third-party/date/BUILD.bzl: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "date", 3 | hdrs = ["include/date/date.h"], 4 | strip_include_prefix = "include", 5 | visibility = ["//visibility:public"], 6 | ) 7 | -------------------------------------------------------------------------------- /third-party/sqlpp11/BUILD.bzl: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "sqlpp11", 3 | hdrs = glob(["include/**"]), 4 | strip_include_prefix = "include", 5 | visibility = ["//visibility:public"], 6 | deps = ["@hinnant_date//:date"], 7 | ) 8 | -------------------------------------------------------------------------------- /third-party/sqlpp11mysql/BUILD.bzl: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "sqlpp11mysql", 3 | srcs = glob([ 4 | "src/**/*.cpp", 5 | "src/**/*.h", 6 | ]), 7 | hdrs = glob(["include/**"]), 8 | strip_include_prefix = "include", 9 | visibility = ["//visibility:public"], 10 | deps = [ 11 | "@boost//:thread", 12 | "@mariadb_connector//:connector", 13 | "@sqlpp11", 14 | ], 15 | ) 16 | -------------------------------------------------------------------------------- /third-party/sqlpp11sqlite/BUILD.bzl: -------------------------------------------------------------------------------- 1 | cc_library( 2 | name = "sqlpp11sqlite", 3 | srcs = glob([ 4 | "src/**/*.cpp", 5 | "src/**/*.h", 6 | ]), 7 | hdrs = glob(["include/**"]), 8 | strip_include_prefix = "include", 9 | visibility = ["//visibility:public"], 10 | deps = [ 11 | "@sqlite3", 12 | "@sqlpp11", 13 | ], 14 | ) 15 | -------------------------------------------------------------------------------- /tools/bazel.rc: -------------------------------------------------------------------------------- 1 | build --cxxopt='-std=c++17' 2 | test --copt='-ggdb3' 3 | test --test_output=errors 4 | 5 | # --config asan: Address sanitizer 6 | build:asan --strip=never 7 | build:asan --copt -fsanitize=address 8 | build:asan --copt -fno-omit-frame-pointer 9 | build:asan --linkopt -fsanitize=address 10 | 11 | # --config tsan: ThreadSanitizer 12 | build:tsan --strip=never 13 | build:tsan --copt -fsanitize=thread 14 | build:tsan --copt -DTHREAD_SANITIZER 15 | build:tsan --copt -DDYNAMIC_ANNOTATIONS_ENABLED=1 16 | build:tsan --copt -DDYNAMIC_ANNOTATIONS_EXTERNAL_IMPL=1 17 | build:tsan --copt -fno-omit-frame-pointer 18 | build:tsan --linkopt -fsanitize=thread 19 | build:tsan --linkopt -ltsan 20 | 21 | # --config msan: Memory sanitizer 22 | build:msan --strip=never 23 | build:msan --copt -fsanitize=memory 24 | build:msan --copt -DADDRESS_SANITIZER 25 | build:msan --copt -fno-omit-frame-pointer 26 | build:msan --linkopt -fsanitize=memory 27 | 28 | # --config ubsan: Undefined Behavior Sanitizer 29 | build:ubsan --strip=never 30 | build:ubsan --copt -fsanitize=undefined 31 | build:ubsan --copt -fno-omit-frame-pointer 32 | build:ubsan --linkopt -fsanitize=undefined 33 | build:ubsan --linkopt -lubsan 34 | 35 | -------------------------------------------------------------------------------- /tools/buildifier: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | buildifier -showlog -mode=fix $(find $(git rev-parse --show-toplevel) | grep -E "WORKSPACE|BUILD(\.(bazel|bzl))?\$") 4 | -------------------------------------------------------------------------------- /tools/ci/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | BAZEL_VERSION=1.2.1 6 | BAZEL_INSTALLER=${PWD}/bazel-installer/install.sh 7 | INSTALLER_PLATFORM=linux-x86_64 8 | BASE="${PWD}/bazel-install" 9 | 10 | # Fetch the Bazel installer 11 | rm -rf ${BASE} 12 | rm -rf ${PWD}/bazel-installer 13 | mkdir ${BASE} 14 | mkdir ${PWD}/bazel-installer 15 | 16 | URL=https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/bazel-${BAZEL_VERSION}-installer-${INSTALLER_PLATFORM}.sh 17 | curl -L -o ${BAZEL_INSTALLER} ${URL} 18 | 19 | # Install bazel inside ${BASE} 20 | bash "${BAZEL_INSTALLER}" \ 21 | --base="${BASE}" \ 22 | --bin="${BASE}/binary" 23 | 24 | export CC=/usr/bin/gcc 25 | export CXX=/usr/bin/g++ 26 | 27 | # Run the build 28 | BAZEL="${BASE}/binary/bazel --bazelrc=${PWD}/tools/bazel.rc" 29 | 30 | ${BAZEL} test //... --verbose_failures 31 | -------------------------------------------------------------------------------- /tools/cpplint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | python tools/cpplint.py --filter=-build/include_order,-whitespace/comments --extensions=h,cc hub/**/*.h hub/**/*.cc 4 | 5 | --------------------------------------------------------------------------------