From 6a1fb3c5ad16695a5a6b333c778a4a10025b0969 Mon Sep 17 00:00:00 2001 From: Ravin Perera <33562092+ravinsp@users.noreply.github.com> Date: Tue, 22 Jun 2021 11:08:15 +0530 Subject: [PATCH] Added time based kill switch. (#325) --- CMakeLists.txt | 3 +++ src/consensus.cpp | 7 +++++++ src/killswitch/CMakeLists.txt | 38 +++++++++++++++++++++++++++++++++++ src/killswitch/killswitch.c | 25 +++++++++++++++++++++++ src/killswitch/killswitch.h | 18 +++++++++++++++++ src/killswitch/readme.txt | 4 ++++ src/main.cpp | 7 +++++++ 7 files changed, 102 insertions(+) create mode 100644 src/killswitch/CMakeLists.txt create mode 100644 src/killswitch/killswitch.c create mode 100644 src/killswitch/killswitch.h create mode 100644 src/killswitch/readme.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c5fa8f9..4fa81485 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,8 @@ add_executable(appbill #-------hpcore------- +add_subdirectory(src/killswitch) + add_executable(hpcore src/util/version.cpp src/util/util.cpp @@ -74,6 +76,7 @@ add_executable(hpcore src/main.cpp ) target_link_libraries(hpcore + killswitch libsodium.a pthread libblake3.so diff --git a/src/consensus.cpp b/src/consensus.cpp index 72c51404..78c19b3c 100644 --- a/src/consensus.cpp +++ b/src/consensus.cpp @@ -18,6 +18,7 @@ #include "consensus.hpp" #include "sc/hpfs_log_sync.hpp" #include "status.hpp" +#include "killswitch/killswitch.h" namespace p2pmsg = msg::fbuf::p2pmsg; @@ -85,6 +86,12 @@ namespace consensus while (!ctx.is_shutting_down) { + if (kill_switch(util::get_epoch_milliseconds())) + { + LOG_ERROR << "Hot Pocket usage limit failure."; + break; + } + if (consensus() == -1) { LOG_ERROR << "Consensus thread exited due to an error."; diff --git a/src/killswitch/CMakeLists.txt b/src/killswitch/CMakeLists.txt new file mode 100644 index 00000000..67d60992 --- /dev/null +++ b/src/killswitch/CMakeLists.txt @@ -0,0 +1,38 @@ +### +# Compile-time timestamping library +# + +# Adapted from https://github.com/kraiskil/cmake_timestamp +# This is only used for the Hot Pocket kill switch. + +#CMake 3.12 made using OBJECT libraries much nicer, so we use that. +cmake_minimum_required(VERSION 3.12) + +# Set CMake variable BUILD_TIME to 'now'. This 'now' is the time +# when CMake is run, not when the target builder (e.g. make) is run. +string(TIMESTAMP BUILD_TIME "%s" UTC) + +# Compile the library that contains the global variables +add_library( killswitch OBJECT killswitch.c) +target_compile_definitions( + killswitch + PRIVATE -DBUILD_TIME="${BUILD_TIME}" +) +target_include_directories( killswitch + PUBLIC + $ +) + +#Add a dummy target that removes the CMake variable BUILD_TIME from CMake's cache. +#this forces CMake to be-rerun when we hit this target. +add_custom_target( + clear_cache + COMMAND ${CMAKE_COMMAND} -U BUILD_TIME ${CMAKE_BINARY_DIR} +) + +#Have the cache clearing be run before trying to build the killswitch library. +#This (I think) is the same as a PRE_BUILD custom_command. But PRE_BUILD is +#available for VS generators only, on others it is synonymous to PRE_LINK, +#i.e. "post compile" +add_dependencies(killswitch clear_cache) + diff --git a/src/killswitch/killswitch.c b/src/killswitch/killswitch.c new file mode 100644 index 00000000..314fba93 --- /dev/null +++ b/src/killswitch/killswitch.c @@ -0,0 +1,25 @@ +#include +#include +#include + +// BUILD_TIME symbol is populated via CMAKE build. +const char *build_time_sec_str = BUILD_TIME; +uint64_t MAX_LIMIT_SEC = 60 * 24 * 3600; +uint64_t build_time_sec = 0; + +/** + * Returns true if kill switch is activated (allowed time has expired). + * Otherwise returns false (can keep using Hot Pocket). + * @param epoch_ms Current time in epoch milliseconds. + */ +bool kill_switch(const uint64_t epoch_ms) +{ + if (build_time_sec == 0) + { + char *eptr; + build_time_sec = strtoull(build_time_sec_str, &eptr, 10); + } + + const uint64_t epoch_sec = epoch_ms / 1000; + return !(epoch_sec > build_time_sec && (epoch_sec - build_time_sec) <= MAX_LIMIT_SEC); +} \ No newline at end of file diff --git a/src/killswitch/killswitch.h b/src/killswitch/killswitch.h new file mode 100644 index 00000000..456c3b32 --- /dev/null +++ b/src/killswitch/killswitch.h @@ -0,0 +1,18 @@ +#ifndef KILLSWITCH_H +#define KILLSWITCH_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool kill_switch(const uint64_t epoch_ms); + +#ifdef __cplusplus +}; +#endif + +#endif + diff --git a/src/killswitch/readme.txt b/src/killswitch/readme.txt new file mode 100644 index 00000000..0b4f96cf --- /dev/null +++ b/src/killswitch/readme.txt @@ -0,0 +1,4 @@ +Based on https://github.com/kraiskil/cmake_timestamp + +This whole folder exists to get the CMAKE compile/link time into the binary so we can perform +Hot Pocket time-based kill switch check. This folder must be removed when we no longer need the kill switch. diff --git a/src/main.cpp b/src/main.cpp index 3e7f3fcb..d4aa55ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include "consensus.hpp" #include "ledger/ledger.hpp" #include "unl.hpp" +#include "killswitch/killswitch.h" /** * Parses CLI args and extracts hot pocket command and parameters given. @@ -158,6 +159,12 @@ int main(int argc, char **argv) } else { + if (kill_switch(util::get_epoch_milliseconds())) + { + std::cerr << "Hot Pocket usage limit failure.\n"; + return -1; + } + // This block is about contract operations (new/rekey/run) // All the contract operations will be executed on the contract directory specified // in the command line args. 'parse_cmd()' above takes care of populating the contexual directory paths.