├── README ├── NEWS ├── m4 ├── .gitignore ├── ax_check_link_flag.m4 ├── ax_check_preproc_flag.m4 ├── ax_check_compile_flag.m4 ├── ax_boost_unit_test_framework.m4 ├── ax_boost_base.m4 └── ax_cxx_compile_stdcxx.m4 ├── ChangeLog ├── README.md ├── AUTHORS ├── autogen.sh ├── .gitignore ├── include └── bitcoin │ ├── client │ ├── version.hpp │ ├── define.hpp │ ├── history.hpp │ └── obelisk_client.hpp │ └── client.hpp ├── test ├── main.cpp └── obelisk_client.cpp ├── examples ├── console │ ├── main.cpp │ ├── read_line.hpp │ ├── client.hpp │ ├── read_line.cpp │ └── client.cpp └── get_height │ └── main.cpp ├── libbitcoin-client-test_runner.sh ├── libbitcoin-client.pc.in ├── Makefile.am ├── configure.ac ├── INSTALL ├── install.sh └── COPYING /README: -------------------------------------------------------------------------------- 1 | See README.md -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | See https://libbitcoin.org -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | /libtool.m4 2 | /lt*.m4 3 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Use command 'git log --oneline --decorate' for latest change log. 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This branch is not usable in its current state. Please see [version3](https://github.com/libbitcoin/libbitcoin-client/tree/version3) for the latest functional branch. 2 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | commits libbitcoin developers 2 | -------------------------------------------- 3 | 420 Eric Voskuil (evoskuil) 4 | 105 Phillip Mienk (pmienk) 5 | 40 William Swanson (swansontec) 6 | 4 Neill Miller (thecodefactory) 7 | 2 Amir Taaki (genjix) 8 | 1 betachen 9 | 1 genjix 10 | 1 hao.chen 11 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ############################################################################### 3 | # Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 4 | # 5 | # GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 6 | # 7 | ############################################################################### 8 | 9 | autoreconf -i 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Autotools: 2 | *.la 3 | *.lo 4 | *.o 5 | .deps 6 | .libs 7 | /aclocal.m4 8 | /autom4te.cache 9 | /build-aux 10 | /config.* 11 | /configure 12 | /libtool 13 | Makefile 14 | Makefile.in 15 | libbitcoin-client.pc 16 | 17 | # IDE's and editors: 18 | *~ 19 | .*.swp 20 | .dirstamp 21 | /*.kdev4 22 | /.cproject 23 | /.project 24 | /.settings 25 | /nbproject 26 | bin 27 | obj 28 | 29 | examples/get_height/get_height 30 | examples/console/libbitcoin_client 31 | -------------------------------------------------------------------------------- /include/bitcoin/client/version.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 3 | // 4 | // GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | #ifndef LIBBITCOIN_CLIENT_VERSION_HPP 8 | #define LIBBITCOIN_CLIENT_VERSION_HPP 9 | 10 | /** 11 | * The semantic version of this repository as: [major].[minor].[patch] 12 | * For interpretation of the versioning scheme see: http://semver.org 13 | */ 14 | 15 | #define LIBBITCOIN_CLIENT_VERSION "4.0.0" 16 | #define LIBBITCOIN_CLIENT_MAJOR_VERSION 4 17 | #define LIBBITCOIN_CLIENT_MINOR_VERSION 0 18 | #define LIBBITCOIN_CLIENT_PATCH_VERSION 0 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /include/bitcoin/client.hpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 3 | // 4 | // GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 5 | // 6 | /////////////////////////////////////////////////////////////////////////////// 7 | #ifndef LIBBITCOIN_CLIENT_HPP 8 | #define LIBBITCOIN_CLIENT_HPP 9 | 10 | /** 11 | * API Users: Include only this header. Direct use of other headers is fragile 12 | * and unsupported as header organization is subject to change. 13 | * 14 | * Maintainers: Do not include this header internal to this library. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #define BOOST_TEST_MODULE libbitcoin_client_test 20 | #include 21 | -------------------------------------------------------------------------------- /examples/console/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "client.hpp" 20 | 21 | int main() 22 | { 23 | client client; 24 | return client.run(); 25 | } 26 | -------------------------------------------------------------------------------- /libbitcoin-client-test_runner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ############################################################################### 3 | # Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 4 | # 5 | # GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 6 | # 7 | ############################################################################### 8 | 9 | # Define tests and options. 10 | #============================================================================== 11 | BOOST_UNIT_TEST_OPTIONS=\ 12 | "--run_test=* "\ 13 | "--show_progress=no "\ 14 | "--detect_memory_leak=0 "\ 15 | "--report_level=no "\ 16 | "--build_info=yes" 17 | 18 | 19 | # Run tests. 20 | #============================================================================== 21 | # ALlow CI to send errors to standard output 22 | if [[ $CI == true ]]; then 23 | ./test/libbitcoin-client-test ${BOOST_UNIT_TEST_OPTIONS} 24 | else 25 | ./test/libbitcoin-client-test ${BOOST_UNIT_TEST_OPTIONS} > test.log 26 | fi 27 | -------------------------------------------------------------------------------- /libbitcoin-client.pc.in: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 3 | # 4 | # GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 5 | # 6 | ############################################################################### 7 | 8 | # Substitutions 9 | #============================================================================== 10 | prefix=@prefix@ 11 | exec_prefix=@exec_prefix@ 12 | libdir=@libdir@ 13 | includedir=@includedir@ 14 | 15 | 16 | # Metadata 17 | #============================================================================== 18 | Name: libbitcoin-client 19 | Description: Bitcoin Client Query Library 20 | URL: https://github.com/libbitcoin/libbitcoin-client 21 | Version: @PACKAGE_VERSION@ 22 | 23 | 24 | # Variables 25 | #============================================================================== 26 | # Dependencies that publish package configuration. 27 | #------------------------------------------------------------------------------ 28 | Requires: libbitcoin-system >= 4.0.0 libbitcoin-protocol >= 4.0.0 29 | 30 | # Include directory and any other required compiler flags. 31 | #------------------------------------------------------------------------------ 32 | Cflags: -I${includedir} 33 | 34 | # Lib directory, lib and any required that do not publish pkg-config. 35 | #------------------------------------------------------------------------------ 36 | Libs: -L${libdir} -lbitcoin-client 37 | 38 | -------------------------------------------------------------------------------- /include/bitcoin/client/define.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #ifndef LIBBITCOIN_CLIENT_DEFINE_HPP 20 | #define LIBBITCOIN_CLIENT_DEFINE_HPP 21 | 22 | #include 23 | 24 | // We use the generic helper definitions in libbitcoin to define BCX_API 25 | // and BCX_INTERNAL. BCX_API is used for the public API symbols. It either DLL 26 | // imports or DLL exports (or does nothing for static build) BCX_INTERNAL is 27 | // used for non-api symbols. 28 | 29 | #if defined BCC_STATIC 30 | #define BCC_API 31 | #define BCC_INTERNAL 32 | #elif defined BCC_DLL 33 | #define BCC_API BC_HELPER_DLL_EXPORT 34 | #define BCC_INTERNAL BC_HELPER_DLL_LOCAL 35 | #else 36 | #define BCC_API BC_HELPER_DLL_IMPORT 37 | #define BCC_INTERNAL BC_HELPER_DLL_LOCAL 38 | #endif 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /examples/get_height/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace bc::system; 24 | using namespace bc::client; 25 | using namespace bc::protocol; 26 | 27 | /** 28 | * A minimal example that connects to a server and fetches height. 29 | */ 30 | int main(int argc, char* argv[]) 31 | { 32 | if (argc != 2) 33 | { 34 | std::cerr << "usage: " << argv[0] << " " << std::endl; 35 | return 1; 36 | } 37 | 38 | const auto completion_handler = [](const code& ec, size_t height) 39 | { 40 | if (ec) 41 | std::cerr << "Failed retrieving height: " << ec.message() << std::endl; 42 | else 43 | std::cout << "Height: " << height << std::endl; 44 | }; 45 | 46 | obelisk_client client; 47 | client.connect(config::endpoint(argv[1])); 48 | 49 | // Make the request. 50 | client.blockchain_fetch_last_height(completion_handler); 51 | client.wait(); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_LINK_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_LINK_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$LDFLAGS 44 | LDFLAGS="$LDFLAGS $4 $1" 45 | AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | LDFLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_LINK_FLAGS 54 | -------------------------------------------------------------------------------- /m4/ax_check_preproc_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's 12 | # preprocessor or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the preprocessor's default 18 | # flags when the check is done. The check is thus made with the flags: 19 | # "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the 20 | # preprocessor to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_PREPROC_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_PREPROC_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$CPPFLAGS 44 | CPPFLAGS="$CPPFLAGS $4 $1" 45 | AC_PREPROC_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | CPPFLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_PREPROC_FLAGS 54 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /include/bitcoin/client/history.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #ifndef LIBBITCOIN_CLIENT_HISTORY_HPP 20 | #define LIBBITCOIN_CLIENT_HISTORY_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace libbitcoin { 27 | namespace client { 28 | 29 | /// This structure is used between client and API callers in v3. 30 | /// This structure models the client-server protocol in v1/v2. 31 | struct BCC_API history 32 | { 33 | typedef std::vector list; 34 | 35 | // Constructor provided for in-place construction. 36 | history(const system::chain::output_point& output, 37 | uint64_t output_height, uint64_t value, 38 | const system::chain::input_point& spend, 39 | uint64_t temporary_checksum) 40 | : output(output), 41 | output_height(output_height), 42 | value(value), 43 | spend(spend), 44 | temporary_checksum(temporary_checksum) 45 | { 46 | } 47 | 48 | /// If there is no output this is null_hash:max. 49 | system::chain::output_point output; 50 | uint64_t output_height; 51 | 52 | /// The satoshi value of the output. 53 | uint64_t value; 54 | 55 | /// If there is no spend this is null_hash:max. 56 | system::chain::input_point spend; 57 | 58 | union 59 | { 60 | /// The height of the spend or max if no spend. 61 | uint64_t spend_height; 62 | 63 | /// During expansion this value temporarily doubles as a checksum. 64 | uint64_t temporary_checksum; 65 | }; 66 | }; 67 | 68 | } // namespace client 69 | } // namespace libbitcoin 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /examples/console/read_line.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #ifndef BITCOIN_CLIENT_READ_LINE_HPP 20 | #define BITCOIN_CLIENT_READ_LINE_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | /* 28 | * Reads lines from the terminal in a separate thread. 29 | * 30 | * A networking thread cannot use the C++ standard library to read from the 31 | * terminal. Once the thread calls std::cin.getline or similar, it becomes 32 | * stuck until the user types something, so the thread cannot handle network 33 | * events at the same time. Therefore, the network stuff and the terminal 34 | * stuff need to run in separate threads. 35 | * 36 | * The simplest solution is to create a thread that simply reads from the 37 | * terminal and transmits the results over a zeromq inproc socket. The main 38 | * thread sends an empty REQ message when it wants to read from the terminal, 39 | * and the reader thread sends back a REP message with whatever the user 40 | * typed. If the main thread sends a non-empty REQ message, the thread quits. 41 | * 42 | * To use this class, first call `show_prompt`. This call will display a 43 | * command prompt and begin reading input in the background. Then, use 44 | * `pollitem` with `zmq_poll` to determine when the line is available. Once 45 | * the line is available, use `get_line` to retrieve it. 46 | * 47 | * If you attempt to destroy this class while reading a line, the destructor 48 | * will block until the user finishes their entry. 49 | */ 50 | class read_line 51 | { 52 | public: 53 | read_line(); 54 | 55 | ~read_line(); 56 | 57 | /** 58 | * Displays a command prompt and begins reading a line in the background. 59 | */ 60 | void show_prompt(); 61 | 62 | /** 63 | * Retrieves the line requested by `show_prompt`. This method will 64 | * return a blank string if no line is available yet. 65 | */ 66 | std::string get_line(); 67 | 68 | virtual bc::protocol::zmq::socket& socket(); 69 | 70 | private: 71 | void run(); 72 | 73 | bc::protocol::zmq::context context_; 74 | bc::protocol::zmq::socket socket_; 75 | std::shared_ptr thread_; 76 | }; 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /examples/console/client.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #ifndef BITCOIN_CLIENT_CLIENT_HPP 20 | #define BITCOIN_CLIENT_CLIENT_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include "read_line.hpp" 28 | 29 | /** 30 | * Command-line interface for talking to the obelisk server. 31 | */ 32 | class client 33 | { 34 | public: 35 | /** 36 | * Constructor. 37 | */ 38 | client(); 39 | 40 | /** 41 | * The main loop for the example application. This loop can be woken up 42 | * by either events from the network or by input from the terminal. 43 | */ 44 | int run(); 45 | 46 | private: 47 | 48 | /** 49 | * The commands. 50 | */ 51 | void cmd_exit(std::stringstream& args); 52 | void cmd_help(std::stringstream& args); 53 | void cmd_connect(std::stringstream& args); 54 | void cmd_disconnect(std::stringstream& args); 55 | void cmd_version(std::stringstream& args); 56 | void cmd_height(std::stringstream& args); 57 | void cmd_history(std::stringstream& args); 58 | void cmd_header(std::stringstream& args); 59 | 60 | /** 61 | * Reads a command from the terminal thread, and processes it appropriately. 62 | */ 63 | void command(); 64 | 65 | /** 66 | * Parses a string argument out of the command line, or prints an error 67 | * message if there is none. 68 | */ 69 | bool read_string(std::stringstream& args, std::string& out, 70 | const std::string& error_message); 71 | 72 | /** 73 | * Reads a bitcoin address from the command-line, or prints an error if 74 | * the address is missing or invalid. 75 | */ 76 | bool read_address(std::stringstream& args, 77 | bc::system::wallet::payment_address& out); 78 | 79 | /** 80 | * Reads a 64 byte hex encoded hash from the command-line, or 81 | * prints an error if the hash is missing or invalid. 82 | */ 83 | bool read_hash(std::stringstream& args, bc::system::hash_digest& out); 84 | 85 | /** 86 | * Private members. 87 | */ 88 | bool done_; 89 | read_line terminal_; 90 | std::shared_ptr connection_; 91 | }; 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /examples/console/read_line.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "read_line.hpp" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace bc::system; 29 | using namespace bc::protocol; 30 | 31 | uint32_t signal_halt = 0; 32 | uint32_t signal_continue = 1; 33 | 34 | read_line::read_line() 35 | : socket_(context_, zmq::socket::role::requester) 36 | { 37 | DEBUG_ONLY(const auto ec =) socket_.bind({ "inproc://terminal" }); 38 | BITCOIN_ASSERT(!ec); 39 | 40 | // The thread must be constructed after the socket is already bound. 41 | thread_ = std::make_shared(std::bind(&read_line::run, this)); 42 | } 43 | 44 | read_line::~read_line() 45 | { 46 | zmq::message message; 47 | message.enqueue_little_endian(signal_halt); 48 | DEBUG_ONLY(const auto ec =) socket_.send(message); 49 | BITCOIN_ASSERT(!ec); 50 | thread_->join(); 51 | } 52 | 53 | void read_line::show_prompt() 54 | { 55 | std::cout << "> " << std::flush; 56 | zmq::message message; 57 | message.enqueue_little_endian(signal_continue); 58 | DEBUG_ONLY(const auto ec =) socket_.send(message); 59 | BITCOIN_ASSERT(!ec); 60 | } 61 | 62 | std::string read_line::get_line() 63 | { 64 | code ec; 65 | zmq::poller poller; 66 | poller.add(socket_); 67 | 68 | if (poller.wait().contains(socket_.id())) 69 | { 70 | zmq::message message; 71 | ec = socket_.receive(message); 72 | BITCOIN_ASSERT(!ec); 73 | return message.dequeue_text(); 74 | } 75 | 76 | return{}; 77 | } 78 | 79 | void read_line::run() 80 | { 81 | zmq::socket socket(context_, zmq::socket::role::replier); 82 | auto ec = socket.connect({ "inproc://terminal" }); 83 | BITCOIN_ASSERT(!ec); 84 | 85 | while (true) 86 | { 87 | uint32_t signal; 88 | zmq::message message; 89 | ec = socket.receive(message); 90 | BITCOIN_ASSERT(!ec); 91 | 92 | if (!message.dequeue(signal) || signal == signal_halt) 93 | break; 94 | 95 | // Read input: 96 | char line[1000]; 97 | std::cin.getline(line, sizeof(line)); 98 | std::string text(line); 99 | 100 | zmq::message response; 101 | response.enqueue(text); 102 | ec = socket.send(response); 103 | BITCOIN_ASSERT(!ec); 104 | } 105 | } 106 | 107 | zmq::socket& read_line::socket() 108 | { 109 | return socket_; 110 | } 111 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 3 | # 4 | # GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 5 | # 6 | ############################################################################### 7 | 8 | # Automake settings. 9 | #============================================================================== 10 | # Look for macros in the m4 subdirectory. 11 | #------------------------------------------------------------------------------ 12 | ACLOCAL_AMFLAGS = -I m4 13 | 14 | 15 | # Distribute, make and install products. 16 | #============================================================================== 17 | # files => ${pkgconfigdir} 18 | #------------------------------------------------------------------------------ 19 | pkgconfig_DATA = \ 20 | libbitcoin-client.pc 21 | 22 | # files => ${docdir} 23 | #------------------------------------------------------------------------------ 24 | doc_DATA = \ 25 | AUTHORS \ 26 | COPYING \ 27 | ChangeLog \ 28 | INSTALL \ 29 | NEWS \ 30 | README 31 | 32 | # src/libbitcoin-client.la => ${libdir} 33 | #------------------------------------------------------------------------------ 34 | lib_LTLIBRARIES = src/libbitcoin-client.la 35 | src_libbitcoin_client_la_CPPFLAGS = -I${srcdir}/include ${bitcoin_system_BUILD_CPPFLAGS} ${bitcoin_protocol_BUILD_CPPFLAGS} 36 | src_libbitcoin_client_la_LIBADD = ${bitcoin_system_LIBS} ${bitcoin_protocol_LIBS} 37 | src_libbitcoin_client_la_SOURCES = \ 38 | src/obelisk_client.cpp 39 | 40 | # local: test/libbitcoin-client-test 41 | #------------------------------------------------------------------------------ 42 | if WITH_TESTS 43 | 44 | TESTS = libbitcoin-client-test_runner.sh 45 | 46 | check_PROGRAMS = test/libbitcoin-client-test 47 | test_libbitcoin_client_test_CPPFLAGS = -I${srcdir}/include ${bitcoin_system_BUILD_CPPFLAGS} ${bitcoin_protocol_BUILD_CPPFLAGS} 48 | test_libbitcoin_client_test_LDADD = src/libbitcoin-client.la ${boost_unit_test_framework_LIBS} ${bitcoin_system_LIBS} ${bitcoin_protocol_LIBS} 49 | test_libbitcoin_client_test_SOURCES = \ 50 | test/main.cpp \ 51 | test/obelisk_client.cpp 52 | 53 | endif WITH_TESTS 54 | 55 | # local: examples/console/console 56 | #------------------------------------------------------------------------------ 57 | if WITH_EXAMPLES 58 | 59 | noinst_PROGRAMS = examples/console/console 60 | examples_console_console_CPPFLAGS = -I${srcdir}/include ${bitcoin_system_BUILD_CPPFLAGS} ${bitcoin_protocol_BUILD_CPPFLAGS} 61 | examples_console_console_LDADD = src/libbitcoin-client.la ${bitcoin_system_LIBS} ${bitcoin_protocol_LIBS} 62 | examples_console_console_SOURCES = \ 63 | examples/console/client.cpp \ 64 | examples/console/client.hpp \ 65 | examples/console/main.cpp \ 66 | examples/console/read_line.cpp \ 67 | examples/console/read_line.hpp 68 | 69 | endif WITH_EXAMPLES 70 | 71 | # local: examples/get_height/get_height 72 | #------------------------------------------------------------------------------ 73 | if WITH_EXAMPLES 74 | 75 | noinst_PROGRAMS += examples/get_height/get_height 76 | examples_get_height_get_height_CPPFLAGS = -I${srcdir}/include ${bitcoin_system_BUILD_CPPFLAGS} ${bitcoin_protocol_BUILD_CPPFLAGS} 77 | examples_get_height_get_height_LDADD = src/libbitcoin-client.la ${bitcoin_system_LIBS} ${bitcoin_protocol_LIBS} 78 | examples_get_height_get_height_SOURCES = \ 79 | examples/get_height/main.cpp 80 | 81 | endif WITH_EXAMPLES 82 | 83 | # files => ${includedir}/bitcoin 84 | #------------------------------------------------------------------------------ 85 | include_bitcoindir = ${includedir}/bitcoin 86 | include_bitcoin_HEADERS = \ 87 | include/bitcoin/client.hpp 88 | 89 | include_bitcoin_clientdir = ${includedir}/bitcoin/client 90 | include_bitcoin_client_HEADERS = \ 91 | include/bitcoin/client/define.hpp \ 92 | include/bitcoin/client/history.hpp \ 93 | include/bitcoin/client/obelisk_client.hpp \ 94 | include/bitcoin/client/version.hpp 95 | 96 | 97 | # Custom make targets. 98 | #============================================================================== 99 | # make target: examples 100 | #------------------------------------------------------------------------------ 101 | target_examples = \ 102 | examples/console/console \ 103 | examples/get_height/get_height 104 | 105 | examples: ${target_examples} 106 | 107 | -------------------------------------------------------------------------------- /m4/ax_boost_unit_test_framework.m4: -------------------------------------------------------------------------------- 1 | # ================================================================================= 2 | # https://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html 3 | # ================================================================================= 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_UNIT_TEST_FRAMEWORK 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for Unit_Test_Framework library from the Boost C++ libraries. The 12 | # macro requires a preceding call to AX_BOOST_BASE. Further documentation 13 | # is available at . 14 | # 15 | # This macro calls: 16 | # 17 | # AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) 18 | # 19 | # And sets: 20 | # 21 | # HAVE_BOOST_UNIT_TEST_FRAMEWORK 22 | # 23 | # LICENSE 24 | # 25 | # Copyright (c) 2008 Thomas Porschberg 26 | # 27 | # Copying and distribution of this file, with or without modification, are 28 | # permitted in any medium without royalty provided the copyright notice 29 | # and this notice are preserved. This file is offered as-is, without any 30 | # warranty. 31 | 32 | #serial 22 33 | 34 | AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], 35 | [ 36 | AC_ARG_WITH([boost-unit-test-framework], 37 | AS_HELP_STRING([--with-boost-unit-test-framework@<:@=special-lib@:>@], 38 | [use the Unit_Test_Framework library from boost - it is possible to specify a certain library for the linker 39 | e.g. --with-boost-unit-test-framework=boost_unit_test_framework-gcc ]), 40 | [ 41 | if test "$withval" = "no"; then 42 | want_boost="no" 43 | elif test "$withval" = "yes"; then 44 | want_boost="yes" 45 | ax_boost_user_unit_test_framework_lib="" 46 | else 47 | want_boost="yes" 48 | ax_boost_user_unit_test_framework_lib="$withval" 49 | fi 50 | ], 51 | [want_boost="yes"] 52 | ) 53 | 54 | if test "x$want_boost" = "xyes"; then 55 | AC_REQUIRE([AC_PROG_CC]) 56 | CPPFLAGS_SAVED="$CPPFLAGS" 57 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 58 | export CPPFLAGS 59 | 60 | LDFLAGS_SAVED="$LDFLAGS" 61 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 62 | export LDFLAGS 63 | 64 | AC_CACHE_CHECK(whether the Boost::Unit_Test_Framework library is available, 65 | ax_cv_boost_unit_test_framework, 66 | [AC_LANG_PUSH([C++]) 67 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], 68 | [[using boost::unit_test::test_suite; 69 | test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); if (test == NULL) { return 1; } else { return 0; }]])], 70 | ax_cv_boost_unit_test_framework=yes, ax_cv_boost_unit_test_framework=no) 71 | AC_LANG_POP([C++]) 72 | ]) 73 | if test "x$ax_cv_boost_unit_test_framework" = "xyes"; then 74 | AC_DEFINE(HAVE_BOOST_UNIT_TEST_FRAMEWORK,,[define if the Boost::Unit_Test_Framework library is available]) 75 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` 76 | 77 | if test "x$ax_boost_user_unit_test_framework_lib" = "x"; then 78 | saved_ldflags="${LDFLAGS}" 79 | for monitor_library in `ls $BOOSTLIBDIR/libboost_unit_test_framework*.so* $BOOSTLIBDIR/libboost_unit_test_framework*.dylib* $BOOSTLIBDIR/libboost_unit_test_framework*.a* 2>/dev/null` ; do 80 | if test -r $monitor_library ; then 81 | libextension=`echo $monitor_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a.*$;\1;'` 82 | ax_lib=${libextension} 83 | link_unit_test_framework="yes" 84 | else 85 | link_unit_test_framework="no" 86 | fi 87 | 88 | if test "x$link_unit_test_framework" = "xyes"; then 89 | BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib" 90 | AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) 91 | break 92 | fi 93 | done 94 | if test "x$link_unit_test_framework" != "xyes"; then 95 | for libextension in `ls $BOOSTLIBDIR/boost_unit_test_framework*.dll* $BOOSTLIBDIR/boost_unit_test_framework*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_unit_test_framework.*\)\.dll.*$;\1;' -e 's;^\(boost_unit_test_framework.*\)\.a.*$;\1;'` ; do 96 | ax_lib=${libextension} 97 | AC_CHECK_LIB($ax_lib, exit, 98 | [BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib"; AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) link_unit_test_framework="yes"; break], 99 | [link_unit_test_framework="no"]) 100 | done 101 | fi 102 | else 103 | link_unit_test_framework="no" 104 | saved_ldflags="${LDFLAGS}" 105 | for ax_lib in boost_unit_test_framework-$ax_boost_user_unit_test_framework_lib $ax_boost_user_unit_test_framework_lib ; do 106 | if test "x$link_unit_test_framework" = "xyes"; then 107 | break; 108 | fi 109 | for unittest_library in `ls $BOOSTLIBDIR/lib${ax_lib}.so* $BOOSTLIBDIR/lib${ax_lib}.a* 2>/dev/null` ; do 110 | if test -r $unittest_library ; then 111 | libextension=`echo $unittest_library | sed 's,.*/,,' | sed -e 's;^lib\(boost_unit_test_framework.*\)\.so.*$;\1;' -e 's;^lib\(boost_unit_test_framework.*\)\.a*$;\1;'` 112 | ax_lib=${libextension} 113 | link_unit_test_framework="yes" 114 | else 115 | link_unit_test_framework="no" 116 | fi 117 | 118 | if test "x$link_unit_test_framework" = "xyes"; then 119 | BOOST_UNIT_TEST_FRAMEWORK_LIB="-l$ax_lib" 120 | AC_SUBST(BOOST_UNIT_TEST_FRAMEWORK_LIB) 121 | break 122 | fi 123 | done 124 | done 125 | fi 126 | if test "x$ax_lib" = "x"; then 127 | AC_MSG_ERROR(Could not find a version of the Boost::Unit_Test_Framework library!) 128 | fi 129 | if test "x$link_unit_test_framework" != "xyes"; then 130 | AC_MSG_ERROR(Could not link against $ax_lib !) 131 | fi 132 | fi 133 | 134 | CPPFLAGS="$CPPFLAGS_SAVED" 135 | LDFLAGS="$LDFLAGS_SAVED" 136 | fi 137 | ]) 138 | -------------------------------------------------------------------------------- /examples/console/client.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "client.hpp" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "read_line.hpp" 27 | 28 | using namespace bc::client; 29 | using namespace bc::protocol; 30 | using namespace bc::system; 31 | using namespace bc::system::chain; 32 | using namespace bc::system::wallet; 33 | 34 | client::client() 35 | : done_(false) 36 | { 37 | } 38 | 39 | void client::cmd_exit(std::stringstream&) 40 | { 41 | done_ = true; 42 | } 43 | 44 | void client::cmd_help(std::stringstream&) 45 | { 46 | std::cout << "Commands:" << std::endl; 47 | std::cout << " exit [ or quit ] - Leave the program" << std::endl; 48 | std::cout << " help - Display this menu" << std::endl; 49 | std::cout << " connect - Connect to a server" << std::endl; 50 | std::cout << " disconnect - Disconnect from the server" << std::endl; 51 | std::cout << " version - Fetch the server's version" << std::endl; 52 | std::cout << " height - Fetch last block height" << std::endl; 53 | std::cout << " header - Fetch a block's header" << std::endl; 54 | std::cout << " history
- Fetch an address' history" << std::endl; 55 | } 56 | 57 | void client::cmd_connect(std::stringstream& args) 58 | { 59 | static constexpr size_t retries = 3; 60 | 61 | std::string server; 62 | if (!read_string(args, server, "error: no server given")) 63 | return; 64 | 65 | std::cout << "Connecting to " << server << std::endl; 66 | 67 | connection_ = std::make_shared(retries); 68 | if (!connection_ || !connection_->connect(config::endpoint(server))) 69 | std::cerr << "Failed to connect to " << server << std::endl; 70 | } 71 | 72 | void client::cmd_disconnect(std::stringstream&) 73 | { 74 | connection_.reset(); 75 | std::cout << "Disconnected from server" << std::endl; 76 | } 77 | 78 | void client::cmd_version(std::stringstream&) 79 | { 80 | if (!connection_) 81 | { 82 | std::cerr << "Connect to a server first." << std::endl; 83 | return; 84 | } 85 | 86 | auto handler = [](const code& ec, const std::string& version) 87 | { 88 | if (ec) 89 | std::cerr << "Failed to retrieve version: " << ec.message() 90 | << std::endl; 91 | else 92 | std::cout << "Version: " << version << std::endl; 93 | }; 94 | 95 | connection_->server_version(handler); 96 | connection_->wait(); 97 | } 98 | 99 | void client::cmd_height(std::stringstream&) 100 | { 101 | if (!connection_) 102 | { 103 | std::cerr << "Connect to a server first." << std::endl; 104 | return; 105 | } 106 | 107 | auto handler = [](const code& ec, size_t height) 108 | { 109 | if (ec) 110 | std::cerr << "Failed to retrieve height: " << ec.message() 111 | << std::endl; 112 | else 113 | std::cout << "Height: " << height << std::endl; 114 | }; 115 | 116 | connection_->blockchain_fetch_last_height(handler); 117 | connection_->wait(); 118 | } 119 | 120 | void client::cmd_history(std::stringstream& args) 121 | { 122 | if (!connection_) 123 | { 124 | std::cerr << "Connect to a server first." << std::endl; 125 | return; 126 | } 127 | 128 | payment_address address; 129 | if (!read_address(args, address)) 130 | return; 131 | 132 | auto handler = [](const code& ec, const history::list& history) 133 | { 134 | if (ec != error::success) 135 | std::cerr << "Failed to retrieve history: " << ec.message() 136 | << std::endl; 137 | else 138 | for (const auto& row: history) 139 | std::cout << "History value: " << row.value << std::endl; 140 | }; 141 | 142 | const auto key = sha256_hash(address.output_script().to_data(false)); 143 | connection_->blockchain_fetch_history4(handler, key); 144 | connection_->wait(); 145 | } 146 | 147 | void client::cmd_header(std::stringstream& args) 148 | { 149 | if (!connection_) 150 | { 151 | std::cerr << "Connect to a server first." << std::endl; 152 | return; 153 | } 154 | 155 | hash_digest hash{}; 156 | if (!read_hash(args, hash)) 157 | return; 158 | 159 | auto handler = [](const code& ec, const header& header) 160 | { 161 | if (ec) 162 | { 163 | std::cerr << "Failed to retrieve block header: " << ec.message() 164 | << std::endl; 165 | return; 166 | } 167 | 168 | std::cout << "Header : " << encode_base16(header.hash()) 169 | << std::endl; 170 | std::cout << "Bits : " << header.bits() << std::endl; 171 | std::cout << "Merkle Tree Hash: " 172 | << encode_base16(header.merkle_root()) << std::endl; 173 | std::cout << "Nonce : " << header.nonce() << std::endl; 174 | std::cout << "Previous Hash : " 175 | << encode_base16(header.previous_block_hash()) << std::endl; 176 | std::cout << "Timestamp : " << header.timestamp() << std::endl; 177 | std::cout << "Version : " << header.version() << std::endl; 178 | }; 179 | 180 | connection_->blockchain_fetch_block_header(handler, hash); 181 | connection_->wait(); 182 | } 183 | 184 | int client::run() 185 | { 186 | static const size_t delay_milliseconds = 100; 187 | 188 | std::cout << "Type \"help\" for supported instructions" << std::endl; 189 | terminal_.show_prompt(); 190 | 191 | const auto terminal_socket_id = terminal_.socket().id(); 192 | zmq::poller poller; 193 | poller.add(terminal_.socket()); 194 | 195 | while (!poller.terminated() && !done_) 196 | { 197 | if (poller.wait(delay_milliseconds).contains(terminal_socket_id)) 198 | command(); 199 | } 200 | 201 | return 0; 202 | } 203 | 204 | void client::command() 205 | { 206 | typedef std::function handler; 207 | typedef std::unordered_map handler_map; 208 | 209 | static const handler_map handlers = 210 | { 211 | { "exit", [this](std::stringstream& args) { cmd_exit(args); } }, 212 | { "quit", [this](std::stringstream& args) { cmd_exit(args); } }, 213 | { "help", [this](std::stringstream& args) { cmd_help(args); } }, 214 | { "connect", [this](std::stringstream& args) { cmd_connect(args); } }, 215 | { "disconnect", [this](std::stringstream& args) { cmd_disconnect(args); } }, 216 | { "version", [this](std::stringstream& args) { cmd_version(args); } }, 217 | { "height", [this](std::stringstream& args) { cmd_height(args); } }, 218 | { "history", [this](std::stringstream& args) { cmd_history(args); } }, 219 | { "header", [this](std::stringstream& args) { cmd_header(args); } } 220 | }; 221 | 222 | std::stringstream reader(terminal_.get_line()); 223 | std::string command; 224 | reader >> command; 225 | 226 | auto command_handler = handlers.find(command); 227 | if (command_handler != handlers.end()) 228 | command_handler->second(reader); 229 | else 230 | std::cout << "Unknown command " << command << std::endl; 231 | 232 | if (!done_) 233 | terminal_.show_prompt(); 234 | } 235 | 236 | bool client::read_string(std::stringstream& args, std::string& out, 237 | const std::string& error_message) 238 | { 239 | args >> out; 240 | if (!out.size()) 241 | { 242 | std::cout << error_message << std::endl; 243 | return false; 244 | } 245 | 246 | return true; 247 | } 248 | 249 | bool client::read_address(std::stringstream& args, payment_address& out) 250 | { 251 | std::string address; 252 | if (!read_string(args, address, "error: no address given")) 253 | return false; 254 | 255 | payment_address payment(address); 256 | if (!payment) 257 | { 258 | std::cout << "Error: invalid address " << address << std::endl; 259 | return false; 260 | } 261 | 262 | out = payment; 263 | return true; 264 | } 265 | 266 | bool client::read_hash(std::stringstream& args, hash_digest& out) 267 | { 268 | std::string hash_string; 269 | if (!read_string(args, hash_string, "error: no hash given")) 270 | return false; 271 | 272 | hash_digest hash{}; 273 | if (!decode_hash(hash, hash_string)) 274 | { 275 | std::cout << "Error: invalid hash " << hash_string << std::endl; 276 | return false; 277 | } 278 | 279 | out = hash; 280 | return true; 281 | } 282 | -------------------------------------------------------------------------------- /test/obelisk_client.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using namespace bc::client; 27 | using namespace bc::protocol; 28 | using namespace bc::system; 29 | using namespace bc::system::wallet; 30 | 31 | // FIXME: This points to a temporary v4 testnet instance. 32 | static const std::string testnet_url = "tcp://testnet2.libbitcoin.net:29091"; 33 | 34 | // Arbitrary values for test cases (from testnet block 800,001). 35 | static const uint32_t test_height = 800001; 36 | static const std::string test_address = "2NGDnSYWMPY1mZCre69wWWgqV1T2wryAXNV"; 37 | static const char test_key[] = "2ef44127d8b0e66eb991f79a8da10e901fc07a82d69a9cfc1ea6e53ae1c66465"; 38 | static const char test_utxo_key[] = "4dda1bb623465ef9c36390975126c1cbff2f5693cc6ad6d3de34c240c092e2e5"; 39 | static const char test_tx_hash[] = "6b0b5509edd6f14c85245f4192097632a7f785d1b2edba0566a2014a29277d73"; 40 | static const char test_block_hash[] = "00000000002889eccd1262e2b7fe893b9839574d9db57755a1c717f88dae73d5"; 41 | 42 | #define CLIENT_TEST_SETUP \ 43 | static const uint32_t retries = 0; \ 44 | obelisk_client client(retries); \ 45 | client.connect(config::endpoint(testnet_url)) 46 | 47 | BOOST_AUTO_TEST_SUITE(stub) 48 | 49 | BOOST_AUTO_TEST_CASE(client__dummy_test__ok) 50 | { 51 | BOOST_REQUIRE_EQUAL(true, true); 52 | } 53 | 54 | BOOST_AUTO_TEST_SUITE_END() 55 | 56 | BOOST_AUTO_TEST_SUITE(network) 57 | 58 | BOOST_AUTO_TEST_CASE(client__fetch_history4__test) 59 | { 60 | CLIENT_TEST_SETUP; 61 | 62 | const uint64_t expected_height = 923346; 63 | const std::string expected_hash = "c331a7e31978f1b7ba4a60c6ebfce6eb713ab1542ddf2fd67bbf0824f9d1a353"; 64 | uint64_t received_height = 0; 65 | std::string received_hash; 66 | 67 | const auto on_done = [&received_hash, &received_height](const code& ec, const history::list& rows) 68 | { 69 | if (ec == error::success) 70 | { 71 | const auto& row = rows.front(); 72 | received_hash = encode_hash(row.output.hash()); 73 | received_height = row.output_height; 74 | } 75 | }; 76 | 77 | client.blockchain_fetch_history4(on_done, hash_literal(test_utxo_key), 0); 78 | client.wait(); 79 | 80 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 81 | BOOST_REQUIRE_EQUAL(received_height, expected_height); 82 | } 83 | 84 | BOOST_AUTO_TEST_CASE(client__subscribe_key__test_ok_and_timeout) 85 | { 86 | CLIENT_TEST_SETUP; 87 | 88 | size_t times_called = 0; 89 | 90 | // This should be called exactly twice. Once for subscription 91 | // success, and then again for subscription timeout. 92 | auto on_done = [×_called](const code& ec, uint16_t, size_t, 93 | const hash_digest&) 94 | { 95 | if (++times_called == 1) 96 | BOOST_REQUIRE_EQUAL(ec, error::success); 97 | else 98 | BOOST_REQUIRE_EQUAL(ec, error::channel_timeout); 99 | }; 100 | 101 | const auto id = client.subscribe_key(on_done, hash_literal(test_key)); 102 | client.monitor(0); 103 | 104 | BOOST_REQUIRE_EQUAL(id, 1); 105 | } 106 | 107 | BOOST_AUTO_TEST_CASE(client__unsubscribe_key__test_ok) 108 | { 109 | CLIENT_TEST_SETUP; 110 | 111 | bool subscribed = false; 112 | uint32_t id = obelisk_client::null_subscription; 113 | 114 | auto subscribe_handler = [&client, &subscribed, &id]() 115 | { 116 | static const auto ten_minutes_in_milliseconds = 600 * 1000; 117 | 118 | auto on_done = [&subscribed](const code& ec, uint16_t, size_t, 119 | const hash_digest&) 120 | { 121 | if (ec == error::success) 122 | subscribed = true; 123 | }; 124 | 125 | id = client.subscribe_key(on_done, hash_literal(test_key)); 126 | BOOST_REQUIRE_EQUAL(id, 1); 127 | client.monitor(ten_minutes_in_milliseconds); 128 | }; 129 | 130 | // Waits until subscribe handler is subscribed and then unsubscribes. 131 | auto unsubscribe_handler = [&client, &subscribed, &id]() 132 | { 133 | zmq::poller poller; 134 | while(!subscribed) 135 | poller.wait(100); 136 | 137 | bool unsubscribe_complete = false; 138 | 139 | auto on_done = [&unsubscribe_complete](const code& ec) 140 | { 141 | BOOST_REQUIRE_EQUAL(ec, error::success); 142 | unsubscribe_complete = true; 143 | }; 144 | 145 | BOOST_REQUIRE(id != obelisk_client::null_subscription); 146 | BOOST_REQUIRE(client.unsubscribe_key(on_done, id) == true); 147 | 148 | poller.wait(2000); 149 | BOOST_REQUIRE(unsubscribe_complete == true); 150 | }; 151 | 152 | std::thread unsubscriber(unsubscribe_handler); 153 | std::thread subscriber(subscribe_handler); 154 | 155 | subscriber.join(); 156 | unsubscriber.join(); 157 | } 158 | 159 | BOOST_AUTO_TEST_CASE(client__fetch_transaction__test) 160 | { 161 | CLIENT_TEST_SETUP; 162 | 163 | const std::string expected_hash = std::string(test_tx_hash); 164 | 165 | std::string received_hash; 166 | const auto on_done = [&received_hash](const code& ec, const chain::transaction& tx) 167 | { 168 | BOOST_REQUIRE_EQUAL(ec, error::success); 169 | if (ec == error::success) 170 | received_hash = encode_hash(tx.hash()); 171 | }; 172 | 173 | client.blockchain_fetch_transaction(on_done, hash_literal(test_tx_hash)); 174 | client.wait(); 175 | 176 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 177 | } 178 | 179 | BOOST_AUTO_TEST_CASE(client__fetch_transaction2__test) 180 | { 181 | CLIENT_TEST_SETUP; 182 | 183 | const std::string expected_hash = std::string(test_tx_hash); 184 | 185 | std::string received_hash; 186 | const auto on_done = [&received_hash](const code& ec, const chain::transaction& tx) 187 | { 188 | BOOST_REQUIRE_EQUAL(ec, error::success); 189 | if (ec == error::success) 190 | received_hash = encode_hash(tx.hash()); 191 | }; 192 | 193 | client.blockchain_fetch_transaction2(on_done, hash_literal(test_tx_hash)); 194 | client.wait(); 195 | 196 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 197 | } 198 | 199 | BOOST_AUTO_TEST_CASE(client__fetch_unspent_outputs__test) 200 | { 201 | CLIENT_TEST_SETUP; 202 | 203 | const auto satoshis = 100000; 204 | const std::string expected_hash = "c331a7e31978f1b7ba4a60c6ebfce6eb713ab1542ddf2fd67bbf0824f9d1a353"; 205 | std::string received_hash; 206 | 207 | const auto on_done = [&received_hash](const code& ec, const chain::points_value& value) 208 | { 209 | if (ec == error::success) 210 | received_hash = encode_hash(value.points.front().hash()); 211 | }; 212 | 213 | client.blockchain_fetch_unspent_outputs(on_done, hash_literal(test_utxo_key), 214 | satoshis, chain::points_value::selection::individual); 215 | client.wait(); 216 | 217 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 218 | } 219 | 220 | BOOST_AUTO_TEST_CASE(client__fetch_last_height__test) 221 | { 222 | CLIENT_TEST_SETUP; 223 | 224 | size_t received_height = 0; 225 | const auto on_done = [&received_height](const code& ec, size_t height) 226 | { 227 | if (ec == error::success) 228 | received_height = height; 229 | }; 230 | 231 | client.blockchain_fetch_last_height(on_done); 232 | client.wait(); 233 | 234 | BOOST_REQUIRE_EQUAL(received_height > 0, true); 235 | } 236 | 237 | BOOST_AUTO_TEST_CASE(client__fetch_last_height__multi_handler_test) 238 | { 239 | CLIENT_TEST_SETUP; 240 | 241 | size_t received_height1 = 0; 242 | size_t received_height2 = 0; 243 | size_t received_height3 = 0; 244 | 245 | const auto handler1 = [&received_height1](const code& ec, size_t height) 246 | { 247 | if (ec == error::success) 248 | received_height1 = height; 249 | }; 250 | 251 | const auto handler2 = [&received_height2](const code& ec, size_t height) 252 | { 253 | if (ec == error::success) 254 | received_height2 = height; 255 | }; 256 | 257 | const auto handler3 = [&received_height3](const code& ec, size_t height) 258 | { 259 | if (ec == error::success) 260 | received_height3 = height; 261 | }; 262 | 263 | client.blockchain_fetch_last_height(handler1); 264 | client.blockchain_fetch_last_height(handler2); 265 | client.blockchain_fetch_last_height(handler3); 266 | client.wait(); 267 | 268 | BOOST_REQUIRE_EQUAL(received_height1 > 0, true); 269 | BOOST_REQUIRE_EQUAL(received_height2 > 0, true); 270 | BOOST_REQUIRE_EQUAL(received_height3 > 0, true); 271 | } 272 | 273 | BOOST_AUTO_TEST_CASE(client__fetch_block_header__height_test) 274 | { 275 | CLIENT_TEST_SETUP; 276 | 277 | const std::string expected_hash = std::string(test_block_hash); 278 | 279 | std::string received_hash; 280 | const auto on_done = [&received_hash](const code& ec, const chain::header& header) 281 | { 282 | if (ec == error::success) 283 | received_hash = encode_hash(header.hash()); 284 | }; 285 | 286 | client.blockchain_fetch_block_header(on_done, test_height); 287 | client.wait(); 288 | 289 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 290 | } 291 | 292 | BOOST_AUTO_TEST_CASE(client__fetch_block_header__hash_test) 293 | { 294 | CLIENT_TEST_SETUP; 295 | 296 | const std::string expected_hash = std::string(test_block_hash); 297 | const std::string expected_previous_hash = "0000000000209b091d6519187be7c2ee205293f25f9f503f90027e25abf8b503"; 298 | 299 | std::string received_hash; 300 | std::string received_previous_hash; 301 | 302 | const auto on_done = [&received_hash, &received_previous_hash](const code& ec, const chain::header& header) 303 | { 304 | if (ec != error::success) 305 | return; 306 | 307 | received_hash = encode_hash(header.hash()); 308 | received_previous_hash = encode_hash(header.previous_block_hash()); 309 | }; 310 | 311 | client.blockchain_fetch_block_header(on_done, test_height); 312 | client.wait(); 313 | 314 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 315 | BOOST_REQUIRE_EQUAL(received_previous_hash, expected_previous_hash); 316 | } 317 | 318 | BOOST_AUTO_TEST_CASE(client__fetch_transaction__index_test) 319 | { 320 | CLIENT_TEST_SETUP; 321 | 322 | const size_t expected_block = test_height; 323 | const size_t expected_index = 1; 324 | 325 | size_t received_block = 9999; 326 | size_t received_index = 9999; 327 | 328 | const auto on_done = [&received_block, &received_index](const code& ec, 329 | size_t block, size_t index) 330 | { 331 | if (ec != error::success) 332 | return; 333 | 334 | received_block = block; 335 | received_index = index; 336 | }; 337 | 338 | client.blockchain_fetch_transaction_index(on_done, hash_literal(test_tx_hash)); 339 | client.wait(); 340 | 341 | BOOST_REQUIRE_EQUAL(received_block, expected_block); 342 | BOOST_REQUIRE_EQUAL(received_index, expected_index); 343 | } 344 | 345 | BOOST_AUTO_TEST_CASE(client__pool_fetch_transaction__test) 346 | { 347 | CLIENT_TEST_SETUP; 348 | 349 | const std::string expected_hash = std::string(test_tx_hash); 350 | 351 | std::string received_hash; 352 | const auto on_done = [&received_hash](const code& ec, const chain::transaction& tx) 353 | { 354 | if (ec == error::success) 355 | received_hash = encode_hash(tx.hash()); 356 | }; 357 | 358 | client.transaction_pool_fetch_transaction(on_done, hash_literal(test_tx_hash)); 359 | client.wait(); 360 | 361 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 362 | } 363 | 364 | BOOST_AUTO_TEST_CASE(client__pool_fetch_transaction2__test) 365 | { 366 | CLIENT_TEST_SETUP; 367 | 368 | const std::string expected_hash = std::string(test_tx_hash); 369 | 370 | std::string received_hash; 371 | const auto on_done = [&received_hash](const code& ec, const chain::transaction& tx) 372 | { 373 | if (ec == error::success) 374 | received_hash = encode_hash(tx.hash()); 375 | }; 376 | 377 | client.transaction_pool_fetch_transaction2(on_done, hash_literal(test_tx_hash)); 378 | client.wait(); 379 | 380 | BOOST_REQUIRE_EQUAL(received_hash, expected_hash); 381 | } 382 | 383 | BOOST_AUTO_TEST_SUITE_END() 384 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 3 | # 4 | # GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 5 | # 6 | ############################################################################### 7 | 8 | # Standard declarations. 9 | #============================================================================== 10 | # Requires Automake 1.14 or newer. 11 | 12 | # Declare the required version of Autoconf. 13 | AC_PREREQ([2.65]) 14 | 15 | # Process command-line arguments and perform initialization and verification. 16 | AC_INIT([libbitcoin-client], [4.0.0], [eric@voskuil.org]) 17 | 18 | # Do compilation tests. 19 | AC_LANG(C++) 20 | 21 | # Specify the temporary directory for build tools. 22 | AC_CONFIG_AUX_DIR([build-aux]) 23 | 24 | # Specify the directory of additional local Autoconf macros. 25 | AC_CONFIG_MACRO_DIR([m4]) 26 | 27 | # Run macros for operation of generated Makefiles, enable non-recursive make. 28 | # Unless [foreign] is specified standard GNU files will be required, 29 | # specifically: AUTHORS, COPYING, INSTALL, NEWS, README and ChangeLog. 30 | AM_INIT_AUTOMAKE([subdir-objects]) 31 | 32 | # Enable C and POSIX extensions that may be disabled on certain platforms. 33 | AC_USE_SYSTEM_EXTENSIONS 34 | 35 | # Enable the archiver. 36 | AM_PROG_AR 37 | 38 | # Initialize libtool. 39 | LT_PREREQ(2.4.2) 40 | 41 | # Enable shared libraries if available, and static if they don't conflict. 42 | LT_INIT 43 | AC_SUBST([LIBTOOL_DEPS]) 44 | 45 | # Determine C++ compiler to use. 46 | AC_PROG_CXX 47 | 48 | # Enable sed for substitution. 49 | AC_PROG_SED 50 | 51 | # Compute the canonical host-system type variable host, including host_os. 52 | AC_CANONICAL_HOST 53 | 54 | # Enable silent rules option. 55 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 56 | 57 | # Check for pkg-config. 58 | PKG_PROG_PKG_CONFIG 59 | AS_IF([test -n "$PKG_CONFIG"], [], 60 | [AC_MSG_ERROR([pkg-config is required but was not found.])]) 61 | 62 | AS_CASE([${enable_static}], 63 | [yes], [AC_SUBST([PKG_CONFIG], ["$PKG_CONFIG --static"])], 64 | []) 65 | 66 | # Declare environment variables that affect the build. 67 | #------------------------------------------------------------------------------ 68 | AC_ARG_VAR([CC], "C compiler to use, such as gcc or clang") 69 | AC_ARG_VAR([CXX], "C++ compiler to use, such as g++ or clang++") 70 | AC_ARG_VAR([PKG_CONFIG_PATH], "Additional directories for package discovery.") 71 | 72 | # Check for baseline language coverage in the compiler for the C++20 standard. 73 | #------------------------------------------------------------------------------ 74 | AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory]) 75 | 76 | 77 | # Process options. 78 | #============================================================================== 79 | # Implement --with-pkgconfigdir and output ${pkgconfigdir}. 80 | #------------------------------------------------------------------------------ 81 | AC_MSG_CHECKING([--with-pkgconfigdir option]) 82 | AC_ARG_WITH([pkgconfigdir], 83 | AS_HELP_STRING([--with-pkgconfigdir=DIR], 84 | [Path to pkgconfig directory. @<:@default=${libdir}/pkgconfig@:>@]), 85 | [pkgconfigdir=$withval], 86 | [pkgconfigdir=${libdir}/pkgconfig]) 87 | AC_MSG_RESULT([$pkgconfigdir]) 88 | AC_SUBST([pkgconfigdir]) 89 | 90 | # Implement --with-tests and declare WITH_TESTS. 91 | #------------------------------------------------------------------------------ 92 | AC_MSG_CHECKING([--with-tests option]) 93 | AC_ARG_WITH([tests], 94 | AS_HELP_STRING([--with-tests], 95 | [Compile with unit tests. @<:@default=yes@:>@]), 96 | [with_tests=$withval], 97 | [with_tests=yes]) 98 | AC_MSG_RESULT([$with_tests]) 99 | AM_CONDITIONAL([WITH_TESTS], [test x$with_tests != xno]) 100 | 101 | # Implement --with-examples and declare WITH_EXAMPLES. 102 | #------------------------------------------------------------------------------ 103 | AC_MSG_CHECKING([--with-examples option]) 104 | AC_ARG_WITH([examples], 105 | AS_HELP_STRING([--with-examples], 106 | [Compile with examples. @<:@default=yes@:>@]), 107 | [with_examples=$withval], 108 | [with_examples=yes]) 109 | AC_MSG_RESULT([$with_examples]) 110 | AM_CONDITIONAL([WITH_EXAMPLES], [test x$with_examples != xno]) 111 | 112 | # Implement --enable-ndebug and define NDEBUG. 113 | #------------------------------------------------------------------------------ 114 | AC_MSG_CHECKING([--enable-ndebug option]) 115 | AC_ARG_ENABLE([ndebug], 116 | AS_HELP_STRING([--enable-ndebug], 117 | [Compile without debug assertions. @<:@default=yes@:>@]), 118 | [enable_ndebug=$enableval], 119 | [enable_ndebug=yes]) 120 | AC_MSG_RESULT([$enable_ndebug]) 121 | AS_CASE([${enable_ndebug}], [yes], AC_DEFINE([NDEBUG])) 122 | 123 | # Inherit --enable-shared and define BOOST_ALL_DYN_LINK. 124 | #------------------------------------------------------------------------------ 125 | AS_CASE([${enable_shared}], [yes], AC_DEFINE([BOOST_ALL_DYN_LINK])) 126 | 127 | # Implement --enable-isystem. 128 | #------------------------------------------------------------------------------ 129 | AC_MSG_CHECKING([--enable-isystem option]) 130 | AC_ARG_ENABLE([isystem], 131 | AS_HELP_STRING([--enable-isystem], 132 | [Substitute -isystem for -I in dependencies. @<:@default=no@:>@]), 133 | [enable_isystem=$enableval], 134 | [enable_isystem=no]) 135 | AC_MSG_RESULT([$enable_isystem]) 136 | 137 | 138 | # Set flags. 139 | #============================================================================== 140 | # Require c++20 for all c++ products. 141 | #------------------------------------------------------------------------------ 142 | AS_CASE([${CC}], [*], 143 | [AX_CHECK_COMPILE_FLAG([-std=c++20], 144 | [CXXFLAGS="$CXXFLAGS -std=c++20"])]) 145 | 146 | # Warn on all stuff. 147 | #------------------------------------------------------------------------------ 148 | AS_CASE([${CC}], [*], 149 | [AX_CHECK_COMPILE_FLAG([-Wall], 150 | [CFLAGS="$CFLAGS -Wall"])]) 151 | 152 | # Warn on all stuff. 153 | #------------------------------------------------------------------------------ 154 | AS_CASE([${CC}], [*], 155 | [AX_CHECK_COMPILE_FLAG([-Wall], 156 | [CXXFLAGS="$CXXFLAGS -Wall"])]) 157 | 158 | # Warn on extra stuff. 159 | #------------------------------------------------------------------------------ 160 | AS_CASE([${CC}], [*], 161 | [AX_CHECK_COMPILE_FLAG([-Wextra], 162 | [CFLAGS="$CFLAGS -Wextra"])]) 163 | 164 | # Warn on extra stuff. 165 | #------------------------------------------------------------------------------ 166 | AS_CASE([${CC}], [*], 167 | [AX_CHECK_COMPILE_FLAG([-Wextra], 168 | [CXXFLAGS="$CXXFLAGS -Wextra"])]) 169 | 170 | # Disallow warning on style order of declarations. 171 | #------------------------------------------------------------------------------ 172 | AS_CASE([${CC}], [*], 173 | [AX_CHECK_COMPILE_FLAG([-Wno-reorder], 174 | [CXXFLAGS="$CXXFLAGS -Wno-reorder"])]) 175 | 176 | # Suppress warning for incomplete field initialization. 177 | #------------------------------------------------------------------------------ 178 | AS_CASE([${CC}], [*], 179 | [AX_CHECK_COMPILE_FLAG([-Wno-missing-field-initializers], 180 | [CXXFLAGS="$CXXFLAGS -Wno-missing-field-initializers"])]) 181 | 182 | # Conform to style. 183 | #------------------------------------------------------------------------------ 184 | AS_CASE([${CC}], [*], 185 | [AX_CHECK_COMPILE_FLAG([-Wno-missing-braces], 186 | [CXXFLAGS="$CXXFLAGS -Wno-missing-braces"])]) 187 | 188 | # Ignore comments within comments or commenting of backslash extended lines. 189 | #------------------------------------------------------------------------------ 190 | AS_CASE([${CC}], [*], 191 | [AX_CHECK_COMPILE_FLAG([-Wno-comment], 192 | [CXXFLAGS="$CXXFLAGS -Wno-comment"])]) 193 | 194 | # Suppress warning for copy of implicitly generated copy constructor. 195 | #------------------------------------------------------------------------------ 196 | AS_CASE([${CC}], [*], 197 | [AX_CHECK_COMPILE_FLAG([-Wno-deprecated-copy], 198 | [CXXFLAGS="$CXXFLAGS -Wno-deprecated-copy"])]) 199 | 200 | # Conflict in stdlib under clang. Enabled in clang only. 201 | #------------------------------------------------------------------------------ 202 | AS_CASE([${CC}], [*clang*], 203 | [AX_CHECK_COMPILE_FLAG([-Wno-mismatched-tags], 204 | [CXXFLAGS="$CXXFLAGS -Wno-mismatched-tags"])]) 205 | 206 | # Protect stack. 207 | #------------------------------------------------------------------------------ 208 | AS_CASE([${CC}], [*], 209 | [AX_CHECK_LINK_FLAG([-fstack-protector], 210 | [LDFLAGS="$LDFLAGS -fstack-protector"])]) 211 | 212 | # Protect stack comprehensively. 213 | #------------------------------------------------------------------------------ 214 | AS_CASE([${CC}], [*], 215 | [AX_CHECK_LINK_FLAG([-fstack-protector-all], 216 | [LDFLAGS="$LDFLAGS -fstack-protector-all"])]) 217 | 218 | 219 | # Check dependencies. 220 | #============================================================================== 221 | # Require Boost of at least version 1.76.0 and output ${boost_CPPFLAGS/LDFLAGS}. 222 | #------------------------------------------------------------------------------ 223 | AS_CASE([${CC}], [*], 224 | [AX_BOOST_BASE([1.76.0], 225 | [AC_SUBST([boost_CPPFLAGS], [${BOOST_CPPFLAGS}]) 226 | AC_SUBST([boost_ISYS_CPPFLAGS], [`echo ${BOOST_CPPFLAGS} | $SED s/^-I/-isystem/g | $SED s/' -I'/' -isystem'/g`]) 227 | AC_SUBST([boost_LDFLAGS], [${BOOST_LDFLAGS}]) 228 | AC_MSG_NOTICE([boost_CPPFLAGS : ${boost_CPPFLAGS}]) 229 | AC_MSG_NOTICE([boost_ISYS_CPPFLAGS : ${boost_ISYS_CPPFLAGS}]) 230 | AC_MSG_NOTICE([boost_LDFLAGS : ${boost_LDFLAGS}])], 231 | [AC_MSG_ERROR([Boost 1.76.0 or later is required but was not found.])])]) 232 | 233 | AS_CASE([${enable_isystem}],[yes], 234 | [AC_SUBST([boost_BUILD_CPPFLAGS], [${boost_ISYS_CPPFLAGS}])], 235 | [AC_SUBST([boost_BUILD_CPPFLAGS], [${boost_CPPFLAGS}])]) 236 | 237 | AC_MSG_NOTICE([boost_BUILD_CPPFLAGS : ${boost_BUILD_CPPFLAGS}]) 238 | 239 | AS_CASE([${with_tests}], [yes], 240 | [AX_BOOST_UNIT_TEST_FRAMEWORK 241 | AC_SUBST([boost_unit_test_framework_LIBS], [${BOOST_UNIT_TEST_FRAMEWORK_LIB}]) 242 | AC_MSG_NOTICE([boost_unit_test_framework_LIBS : ${boost_unit_test_framework_LIBS}])], 243 | [AC_SUBST([boost_unit_test_framework_LIBS], [])]) 244 | 245 | # Require bitcoin-system of at least version 4.0.0 and output ${bitcoin_system_CPPFLAGS/LIBS/PKG}. 246 | #------------------------------------------------------------------------------ 247 | PKG_CHECK_MODULES([bitcoin_system], [libbitcoin-system >= 4.0.0], 248 | [bitcoin_system_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libbitcoin-system >= 4.0.0" 2>/dev/null`" 249 | bitcoin_system_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libbitcoin-system >= 4.0.0" 2>/dev/null`"], 250 | [AC_MSG_ERROR([libbitcoin-system >= 4.0.0 is required but was not found.])]) 251 | AC_SUBST([bitcoin_system_PKG], ['libbitcoin-system >= 4.0.0']) 252 | AC_SUBST([bitcoin_system_CPPFLAGS], [${bitcoin_system_CFLAGS}]) 253 | AS_IF([test x${bitcoin_system_INCLUDEDIR} != "x"], 254 | [AC_SUBST([bitcoin_system_ISYS_CPPFLAGS], ["-isystem${bitcoin_system_INCLUDEDIR} ${bitcoin_system_OTHER_CFLAGS}"])], 255 | [AC_SUBST([bitcoin_system_ISYS_CPPFLAGS], [${bitcoin_system_OTHER_CFLAGS}])]) 256 | AC_MSG_NOTICE([bitcoin_system_CPPFLAGS : ${bitcoin_system_CPPFLAGS}]) 257 | AC_MSG_NOTICE([bitcoin_system_ISYS_CPPFLAGS : ${bitcoin_system_ISYS_CPPFLAGS}]) 258 | AC_MSG_NOTICE([bitcoin_system_OTHER_CFLAGS : ${bitcoin_system_OTHER_CFLAGS}]) 259 | AC_MSG_NOTICE([bitcoin_system_INCLUDEDIR : ${bitcoin_system_INCLUDEDIR}]) 260 | AC_MSG_NOTICE([bitcoin_system_LIBS : ${bitcoin_system_LIBS}]) 261 | 262 | AS_CASE([${enable_isystem}],[yes], 263 | [AC_SUBST([bitcoin_system_BUILD_CPPFLAGS], [${bitcoin_system_ISYS_CPPFLAGS}])], 264 | [AC_SUBST([bitcoin_system_BUILD_CPPFLAGS], [${bitcoin_system_CPPFLAGS}])]) 265 | 266 | AC_MSG_NOTICE([bitcoin_system_BUILD_CPPFLAGS : ${bitcoin_system_BUILD_CPPFLAGS}]) 267 | 268 | # Require bitcoin-protocol of at least version 4.0.0 and output ${bitcoin_protocol_CPPFLAGS/LIBS/PKG}. 269 | #------------------------------------------------------------------------------ 270 | PKG_CHECK_MODULES([bitcoin_protocol], [libbitcoin-protocol >= 4.0.0], 271 | [bitcoin_protocol_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libbitcoin-protocol >= 4.0.0" 2>/dev/null`" 272 | bitcoin_protocol_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libbitcoin-protocol >= 4.0.0" 2>/dev/null`"], 273 | [AC_MSG_ERROR([libbitcoin-protocol >= 4.0.0 is required but was not found.])]) 274 | AC_SUBST([bitcoin_protocol_PKG], ['libbitcoin-protocol >= 4.0.0']) 275 | AC_SUBST([bitcoin_protocol_CPPFLAGS], [${bitcoin_protocol_CFLAGS}]) 276 | AS_IF([test x${bitcoin_protocol_INCLUDEDIR} != "x"], 277 | [AC_SUBST([bitcoin_protocol_ISYS_CPPFLAGS], ["-isystem${bitcoin_protocol_INCLUDEDIR} ${bitcoin_protocol_OTHER_CFLAGS}"])], 278 | [AC_SUBST([bitcoin_protocol_ISYS_CPPFLAGS], [${bitcoin_protocol_OTHER_CFLAGS}])]) 279 | AC_MSG_NOTICE([bitcoin_protocol_CPPFLAGS : ${bitcoin_protocol_CPPFLAGS}]) 280 | AC_MSG_NOTICE([bitcoin_protocol_ISYS_CPPFLAGS : ${bitcoin_protocol_ISYS_CPPFLAGS}]) 281 | AC_MSG_NOTICE([bitcoin_protocol_OTHER_CFLAGS : ${bitcoin_protocol_OTHER_CFLAGS}]) 282 | AC_MSG_NOTICE([bitcoin_protocol_INCLUDEDIR : ${bitcoin_protocol_INCLUDEDIR}]) 283 | AC_MSG_NOTICE([bitcoin_protocol_LIBS : ${bitcoin_protocol_LIBS}]) 284 | 285 | AS_CASE([${enable_isystem}],[yes], 286 | [AC_SUBST([bitcoin_protocol_BUILD_CPPFLAGS], [${bitcoin_protocol_ISYS_CPPFLAGS}])], 287 | [AC_SUBST([bitcoin_protocol_BUILD_CPPFLAGS], [${bitcoin_protocol_CPPFLAGS}])]) 288 | 289 | AC_MSG_NOTICE([bitcoin_protocol_BUILD_CPPFLAGS : ${bitcoin_protocol_BUILD_CPPFLAGS}]) 290 | 291 | 292 | # Process outputs into templates. 293 | #============================================================================== 294 | AC_CONFIG_FILES([Makefile libbitcoin-client.pc]) 295 | AC_OUTPUT 296 | -------------------------------------------------------------------------------- /include/bitcoin/client/obelisk_client.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS) 3 | * 4 | * This file is part of libbitcoin. 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #ifndef LIBBITCOIN_CLIENT_OBELISK_CLIENT_HPP 20 | #define LIBBITCOIN_CLIENT_OBELISK_CLIENT_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace libbitcoin { 28 | namespace client { 29 | 30 | /// Structure used for passing connection settings for a server. 31 | struct BCC_API connection_settings 32 | { 33 | int32_t retries; 34 | system::config::endpoint server; 35 | system::config::endpoint block_server; 36 | system::config::endpoint transaction_server; 37 | system::config::authority socks; 38 | protocol::zmq::sodium server_public_key; 39 | protocol::zmq::sodium client_private_key; 40 | }; 41 | 42 | /// Client implements a router-dealer interface to communicate with 43 | /// the server over either public or secure sockets. 44 | class BCC_API obelisk_client 45 | { 46 | public: 47 | static const auto null_subscription = bc::max_uint32; 48 | 49 | typedef std::function command_handler; 51 | typedef std::unordered_map command_map; 52 | 53 | // Subscription/notification handler types. 54 | //------------------------------------------------------------------------- 55 | 56 | typedef std::function update_handler; 58 | typedef std::function 59 | block_update_handler; 60 | typedef std::function 61 | transaction_update_handler; 62 | 63 | // Fetch handler types. 64 | //------------------------------------------------------------------------- 65 | 66 | typedef std::function result_handler; 67 | typedef std::function height_handler; 68 | typedef std::function transaction_index_handler; 69 | typedef std::function block_handler; 70 | typedef std::function block_header_handler; 71 | typedef std::function compact_filter_handler; 72 | typedef std::function compact_filter_checkpoint_handler; 73 | typedef std::function compact_filter_headers_handler; 74 | typedef std::function transaction_handler; 75 | typedef std::function points_value_handler; 76 | typedef std::function history_handler; 77 | typedef std::function hash_list_handler; 78 | typedef std::function version_handler; 79 | 80 | // Used for mapping specific requests to specific handlers 81 | // (allowing support for different handlers for different client 82 | // API calls on a per-client instance basis). 83 | typedef std::unordered_map result_handler_map; 84 | typedef std::unordered_map height_handler_map; 85 | typedef std::unordered_map transaction_index_handler_map; 86 | typedef std::unordered_map block_handler_map; 87 | typedef std::unordered_map block_header_handler_map; 88 | typedef std::unordered_map compact_filter_handler_map; 89 | typedef std::unordered_map compact_filter_checkpoint_handler_map; 90 | typedef std::unordered_map compact_filter_headers_handler_map; 91 | typedef std::unordered_map transaction_handler_map; 92 | typedef std::unordered_map history_handler_map; 93 | typedef std::unordered_map> subscription_handler_map; 95 | typedef std::unordered_map> unsubscription_handler_map; 97 | typedef std::unordered_map hash_list_handler_map; 98 | typedef std::unordered_map version_handler_map; 99 | 100 | /// Construct an instance of the client. 101 | obelisk_client(int32_t retries=5); 102 | 103 | ~obelisk_client(); 104 | 105 | /// Connect to the specified endpoint using the provided keys. 106 | bool connect(const system::config::endpoint& address, 107 | const system::config::authority& socks_proxy, 108 | const protocol::zmq::sodium& server_public_key, 109 | const protocol::zmq::sodium& client_private_key); 110 | 111 | /// Connect to the specified endpoint. 112 | bool connect(const system::config::endpoint& address); 113 | 114 | /// Connect using the provided settings. 115 | bool connect(const connection_settings& settings); 116 | 117 | /// Wait for server to respond to queries, until timeout. 118 | void wait(uint32_t timeout_milliseconds=30000); 119 | 120 | /// Monitor for subscription notifications, until timeout. 121 | void monitor(uint32_t timeout_milliseconds=30000); 122 | 123 | // Fetchers. 124 | //------------------------------------------------------------------------- 125 | 126 | void server_version(version_handler handler); 127 | 128 | void transaction_pool_broadcast(result_handler handler, 129 | const system::chain::transaction& tx); 130 | 131 | void transaction_pool_validate2(result_handler handler, 132 | const system::chain::transaction& tx); 133 | 134 | void transaction_pool_fetch_transaction(transaction_handler handler, 135 | const system::hash_digest& tx_hash); 136 | 137 | void transaction_pool_fetch_transaction2(transaction_handler handler, 138 | const system::hash_digest& tx_hash); 139 | 140 | void blockchain_broadcast(result_handler handler, 141 | const system::chain::block& block); 142 | 143 | void blockchain_validate(result_handler handler, 144 | const system::chain::block& block); 145 | 146 | void blockchain_fetch_transaction(transaction_handler handler, 147 | const system::hash_digest& tx_hash); 148 | 149 | void blockchain_fetch_transaction2(transaction_handler handler, 150 | const system::hash_digest& tx_hash); 151 | 152 | void blockchain_fetch_last_height(height_handler handler); 153 | 154 | void blockchain_fetch_block(block_handler handler, uint32_t height); 155 | 156 | void blockchain_fetch_block(block_handler handler, 157 | const system::hash_digest& block_hash); 158 | 159 | void blockchain_fetch_block_header(block_header_handler handler, 160 | uint32_t height); 161 | 162 | void blockchain_fetch_block_header(block_header_handler handler, 163 | const system::hash_digest& block_hash); 164 | 165 | void blockchain_fetch_transaction_index(transaction_index_handler handler, 166 | const system::hash_digest& tx_hash); 167 | 168 | void blockchain_fetch_block_height(height_handler handler, 169 | const system::hash_digest& block_hash); 170 | 171 | void blockchain_fetch_block_transaction_hashes( 172 | hash_list_handler handler, uint32_t height); 173 | 174 | void blockchain_fetch_block_transaction_hashes( 175 | hash_list_handler handler, const system::hash_digest& block_hash); 176 | 177 | void blockchain_fetch_compact_filter(compact_filter_handler handler, 178 | uint8_t filter_type, uint32_t height); 179 | 180 | void blockchain_fetch_compact_filter(compact_filter_handler handler, 181 | uint8_t filter_type, const system::hash_digest& block_hash); 182 | 183 | void blockchain_fetch_compact_filter_headers( 184 | compact_filter_headers_handler handler, uint8_t filter_type, 185 | uint32_t start_height, const system::hash_digest& stop_hash); 186 | 187 | void blockchain_fetch_compact_filter_headers( 188 | compact_filter_headers_handler handler, uint8_t filter_type, 189 | uint32_t start_height, uint32_t stop_height); 190 | 191 | void blockchain_fetch_compact_filter_checkpoint( 192 | compact_filter_checkpoint_handler handler, uint8_t filter_type, 193 | const system::hash_digest& stop_hash); 194 | 195 | // void blockchain_fetch_compact_filter_checkpoint( 196 | // compact_filter_checkpoint_handler handler, uint8_t filter_type, 197 | // uint32_t stop_height); 198 | 199 | void blockchain_fetch_history4(history_handler handler, 200 | const system::hash_digest& key, uint32_t from_height=0); 201 | 202 | void blockchain_fetch_unspent_outputs(points_value_handler handler, 203 | const system::hash_digest& key, uint64_t satoshi, 204 | system::chain::points_value::selection algorithm); 205 | 206 | // Subscribers. 207 | //------------------------------------------------------------------------- 208 | 209 | // Subscribe to a payment key. Return value can be used to unsubscribe. 210 | uint32_t subscribe_key(update_handler handler, 211 | const system::hash_digest& key); 212 | 213 | bool subscribe_block(const system::config::endpoint& address, 214 | block_update_handler on_update); 215 | 216 | bool subscribe_transaction(const system::config::endpoint& address, 217 | transaction_update_handler on_update); 218 | 219 | // Unsubscribers. 220 | //------------------------------------------------------------------------- 221 | 222 | bool unsubscribe_key(result_handler handler, uint32_t subscription); 223 | 224 | private: 225 | // Attach handlers for all supported client-server operations. 226 | void attach_handlers(); 227 | 228 | // Used to handle a request immediately, on early detection of error. 229 | void handle_immediate(const std::string& command, uint32_t id, 230 | const system::code& ec); 231 | 232 | // Determines if any requests have not been handled. 233 | bool requests_outstanding(); 234 | 235 | // Determines if any notification requests have not been handled. 236 | bool subscribe_requests_outstanding(); 237 | 238 | // Calls all remaining/expired handlers with the specified error. 239 | void clear_outstanding_requests(const system::code& ec); 240 | 241 | // Calls all remaining/expired notification handlers with the specified 242 | // error. 243 | void clear_outstanding_subscribe_requests(const system::code& ec); 244 | 245 | // Sends an outgoing request via the internal router. 246 | bool send_request(const std::string& command, uint32_t id, 247 | const system::data_chunk& payload, bool subscription=false); 248 | 249 | // Forward incoming client router requests to the server. 250 | void forward_message(protocol::zmq::socket& source, 251 | protocol::zmq::socket& sink); 252 | 253 | // Process server responses. 254 | void process_response(protocol::zmq::socket& socket); 255 | 256 | // After notifying the server of unsubscribe, this terminates any client 257 | // side monitoring state for the subscription. 258 | bool terminate_unsubscriber(uint32_t subscription); 259 | 260 | protocol::zmq::context context_; 261 | 262 | // Sockets that connect to external libbitcoin services. 263 | protocol::zmq::socket socket_; 264 | protocol::zmq::socket subscribe_socket_; 265 | protocol::zmq::socket block_socket_; 266 | protocol::zmq::socket transaction_socket_; 267 | 268 | // Internal socket pair for client request forwarding to router 269 | // (that then forwards to server). 270 | protocol::zmq::socket dealer_; 271 | protocol::zmq::socket router_; 272 | 273 | // Internal socket pair for client subscription request forwarding to router 274 | // (that then forwards to server). 275 | protocol::zmq::socket subscribe_dealer_; 276 | protocol::zmq::socket subscribe_router_; 277 | 278 | block_update_handler on_block_update_; 279 | transaction_update_handler on_transaction_update_; 280 | int32_t retries_; 281 | bool secure_; 282 | system::config::endpoint worker_; 283 | system::config::endpoint subscribe_worker_; 284 | uint32_t last_request_index_; 285 | command_map command_handlers_; 286 | result_handler_map result_handlers_; 287 | height_handler_map height_handlers_; 288 | transaction_index_handler_map transaction_index_handlers_; 289 | block_handler_map block_handlers_; 290 | block_header_handler_map block_header_handlers_; 291 | compact_filter_handler_map compact_filter_handlers_; 292 | compact_filter_checkpoint_handler_map compact_filter_checkpoint_handlers_; 293 | compact_filter_headers_handler_map compact_filter_headers_handlers_; 294 | transaction_handler_map transaction_handlers_; 295 | history_handler_map history_handlers_; 296 | subscription_handler_map subscription_handlers_; 297 | unsubscription_handler_map unsubscription_handlers_; 298 | hash_list_handler_map hash_list_handlers_; 299 | version_handler_map version_handlers_; 300 | 301 | // Protects subscription_handlers_ 302 | system::upgrade_mutex subscription_lock_; 303 | }; 304 | 305 | } // namespace client 306 | } // namespace libbitcoin 307 | 308 | #endif 309 | -------------------------------------------------------------------------------- /m4/ax_boost_base.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_boost_base.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Test for the Boost C++ libraries of a particular version (or newer) 12 | # 13 | # If no path to the installed boost library is given the macro searchs 14 | # under /usr, /usr/local, /opt and /opt/local and evaluates the 15 | # $BOOST_ROOT environment variable. Further documentation is available at 16 | # . 17 | # 18 | # This macro calls: 19 | # 20 | # AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) 21 | # 22 | # And sets: 23 | # 24 | # HAVE_BOOST 25 | # 26 | # LICENSE 27 | # 28 | # Copyright (c) 2008 Thomas Porschberg 29 | # Copyright (c) 2009 Peter Adolphs 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. This file is offered as-is, without any 34 | # warranty. 35 | 36 | #serial 49 37 | 38 | # example boost program (need to pass version) 39 | m4_define([_AX_BOOST_BASE_PROGRAM], 40 | [AC_LANG_PROGRAM([[ 41 | #include 42 | ]],[[ 43 | (void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))])); 44 | ]])]) 45 | 46 | AC_DEFUN([AX_BOOST_BASE], 47 | [ 48 | AC_ARG_WITH([boost], 49 | [AS_HELP_STRING([--with-boost@<:@=ARG@:>@], 50 | [use Boost library from a standard location (ARG=yes), 51 | from the specified location (ARG=), 52 | or disable it (ARG=no) 53 | @<:@ARG=yes@:>@ ])], 54 | [ 55 | AS_CASE([$withval], 56 | [no],[want_boost="no";_AX_BOOST_BASE_boost_path=""], 57 | [yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""], 58 | [want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"]) 59 | ], 60 | [want_boost="yes"]) 61 | 62 | 63 | AC_ARG_WITH([boost-libdir], 64 | [AS_HELP_STRING([--with-boost-libdir=LIB_DIR], 65 | [Force given directory for boost libraries. 66 | Note that this will override library path detection, 67 | so use this parameter only if default library detection fails 68 | and you know exactly where your boost libraries are located.])], 69 | [ 70 | AS_IF([test -d "$withval"], 71 | [_AX_BOOST_BASE_boost_lib_path="$withval"], 72 | [AC_MSG_ERROR([--with-boost-libdir expected directory name])]) 73 | ], 74 | [_AX_BOOST_BASE_boost_lib_path=""]) 75 | 76 | BOOST_LDFLAGS="" 77 | BOOST_CPPFLAGS="" 78 | AS_IF([test "x$want_boost" = "xyes"], 79 | [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])]) 80 | AC_SUBST(BOOST_CPPFLAGS) 81 | AC_SUBST(BOOST_LDFLAGS) 82 | ]) 83 | 84 | 85 | # convert a version string in $2 to numeric and affect to polymorphic var $1 86 | AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[ 87 | AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"]) 88 | _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'` 89 | _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'` 90 | AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"], 91 | [AC_MSG_ERROR([You should at least specify libboost major version])]) 92 | _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'` 93 | AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"], 94 | [_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"]) 95 | _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` 96 | AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"], 97 | [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"]) 98 | _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor` 99 | AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET) 100 | ]) 101 | 102 | dnl Run the detection of boost should be run only if $want_boost 103 | AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[ 104 | _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1]) 105 | succeeded=no 106 | 107 | 108 | AC_REQUIRE([AC_CANONICAL_HOST]) 109 | dnl On 64-bit systems check for system libraries in both lib64 and lib. 110 | dnl The former is specified by FHS, but e.g. Debian does not adhere to 111 | dnl this (as it rises problems for generic multi-arch support). 112 | dnl The last entry in the list is chosen by default when no libraries 113 | dnl are found, e.g. when only header-only libraries are installed! 114 | AS_CASE([${host_cpu}], 115 | [x86_64],[libsubdirs="lib64 libx32 lib lib64"], 116 | [mips*64*],[libsubdirs="lib64 lib32 lib lib64"], 117 | [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k],[libsubdirs="lib64 lib lib64"], 118 | [libsubdirs="lib"] 119 | ) 120 | 121 | dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give 122 | dnl them priority over the other paths since, if libs are found there, they 123 | dnl are almost assuredly the ones desired. 124 | AS_CASE([${host_cpu}], 125 | [i?86],[multiarch_libsubdir="lib/i386-${host_os}"], 126 | [armv7l],[multiarch_libsubdir="lib/arm-${host_os}"], 127 | [multiarch_libsubdir="lib/${host_cpu}-${host_os}"] 128 | ) 129 | 130 | dnl first we check the system location for boost libraries 131 | dnl this location ist chosen if boost libraries are installed with the --layout=system option 132 | dnl or if you install boost with RPM 133 | AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[ 134 | AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"]) 135 | AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[ 136 | AC_MSG_RESULT([yes]) 137 | BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include" 138 | for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do 139 | AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"]) 140 | AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[ 141 | AC_MSG_RESULT([yes]) 142 | BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"; 143 | break; 144 | ], 145 | [AC_MSG_RESULT([no])]) 146 | done],[ 147 | AC_MSG_RESULT([no])]) 148 | ],[ 149 | if test X"$cross_compiling" = Xyes; then 150 | search_libsubdirs=$multiarch_libsubdir 151 | else 152 | search_libsubdirs="$multiarch_libsubdir $libsubdirs" 153 | fi 154 | for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do 155 | if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then 156 | for libsubdir in $search_libsubdirs ; do 157 | if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 158 | done 159 | BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir" 160 | BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include" 161 | break; 162 | fi 163 | done 164 | ]) 165 | 166 | dnl overwrite ld flags if we have required special directory with 167 | dnl --with-boost-libdir parameter 168 | AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"], 169 | [BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"]) 170 | 171 | AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)]) 172 | CPPFLAGS_SAVED="$CPPFLAGS" 173 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 174 | export CPPFLAGS 175 | 176 | LDFLAGS_SAVED="$LDFLAGS" 177 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 178 | export LDFLAGS 179 | 180 | AC_REQUIRE([AC_PROG_CXX]) 181 | AC_LANG_PUSH(C++) 182 | AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ 183 | AC_MSG_RESULT(yes) 184 | succeeded=yes 185 | found_system=yes 186 | ],[ 187 | ]) 188 | AC_LANG_POP([C++]) 189 | 190 | 191 | 192 | dnl if we found no boost with system layout we search for boost libraries 193 | dnl built and installed without the --layout=system option or for a staged(not installed) version 194 | if test "x$succeeded" != "xyes" ; then 195 | CPPFLAGS="$CPPFLAGS_SAVED" 196 | LDFLAGS="$LDFLAGS_SAVED" 197 | BOOST_CPPFLAGS= 198 | if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then 199 | BOOST_LDFLAGS= 200 | fi 201 | _version=0 202 | if test -n "$_AX_BOOST_BASE_boost_path" ; then 203 | if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then 204 | for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do 205 | _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` 206 | V_CHECK=`expr $_version_tmp \> $_version` 207 | if test "x$V_CHECK" = "x1" ; then 208 | _version=$_version_tmp 209 | fi 210 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` 211 | BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE" 212 | done 213 | dnl if nothing found search for layout used in Windows distributions 214 | if test -z "$BOOST_CPPFLAGS"; then 215 | if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then 216 | BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path" 217 | fi 218 | fi 219 | dnl if we found something and BOOST_LDFLAGS was unset before 220 | dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here. 221 | if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then 222 | for libsubdir in $libsubdirs ; do 223 | if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 224 | done 225 | BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir" 226 | fi 227 | fi 228 | else 229 | if test "x$cross_compiling" != "xyes" ; then 230 | for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do 231 | if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then 232 | for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do 233 | _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` 234 | V_CHECK=`expr $_version_tmp \> $_version` 235 | if test "x$V_CHECK" = "x1" ; then 236 | _version=$_version_tmp 237 | best_path=$_AX_BOOST_BASE_boost_path 238 | fi 239 | done 240 | fi 241 | done 242 | 243 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` 244 | BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" 245 | if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then 246 | for libsubdir in $libsubdirs ; do 247 | if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 248 | done 249 | BOOST_LDFLAGS="-L$best_path/$libsubdir" 250 | fi 251 | fi 252 | 253 | if test -n "$BOOST_ROOT" ; then 254 | for libsubdir in $libsubdirs ; do 255 | if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi 256 | done 257 | if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then 258 | version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` 259 | stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` 260 | stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` 261 | V_CHECK=`expr $stage_version_shorten \>\= $_version` 262 | if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then 263 | AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) 264 | BOOST_CPPFLAGS="-I$BOOST_ROOT" 265 | BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" 266 | fi 267 | fi 268 | fi 269 | fi 270 | 271 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" 272 | export CPPFLAGS 273 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" 274 | export LDFLAGS 275 | 276 | AC_LANG_PUSH(C++) 277 | AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ 278 | AC_MSG_RESULT(yes) 279 | succeeded=yes 280 | found_system=yes 281 | ],[ 282 | ]) 283 | AC_LANG_POP([C++]) 284 | fi 285 | 286 | if test "x$succeeded" != "xyes" ; then 287 | if test "x$_version" = "x0" ; then 288 | AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) 289 | else 290 | AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) 291 | fi 292 | # execute ACTION-IF-NOT-FOUND (if present): 293 | ifelse([$3], , :, [$3]) 294 | else 295 | AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) 296 | # execute ACTION-IF-FOUND (if present): 297 | ifelse([$2], , :, [$2]) 298 | fi 299 | 300 | CPPFLAGS="$CPPFLAGS_SAVED" 301 | LDFLAGS="$LDFLAGS_SAVED" 302 | 303 | ]) 304 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell commands `./configure; make; make install' should 16 | configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf limitation. Until the limitation is lifted, you can use 313 | this workaround: 314 | 315 | CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 316 | 317 | `configure' Invocation 318 | ====================== 319 | 320 | `configure' recognizes the following options to control how it 321 | operates. 322 | 323 | `--help' 324 | `-h' 325 | Print a summary of all of the options to `configure', and exit. 326 | 327 | `--help=short' 328 | `--help=recursive' 329 | Print a summary of the options unique to this package's 330 | `configure', and exit. The `short' variant lists options used 331 | only in the top level, while the `recursive' variant lists options 332 | also present in any nested packages. 333 | 334 | `--version' 335 | `-V' 336 | Print the version of Autoconf used to generate the `configure' 337 | script, and exit. 338 | 339 | `--cache-file=FILE' 340 | Enable the cache: use and save the results of the tests in FILE, 341 | traditionally `config.cache'. FILE defaults to `/dev/null' to 342 | disable caching. 343 | 344 | `--config-cache' 345 | `-C' 346 | Alias for `--cache-file=config.cache'. 347 | 348 | `--quiet' 349 | `--silent' 350 | `-q' 351 | Do not print messages saying which checks are being made. To 352 | suppress all normal output, redirect it to `/dev/null' (any error 353 | messages will still be shown). 354 | 355 | `--srcdir=DIR' 356 | Look for the package's source code in directory DIR. Usually 357 | `configure' can determine that directory automatically. 358 | 359 | `--prefix=DIR' 360 | Use DIR as the installation prefix. *note Installation Names:: 361 | for more details, including other options available for fine-tuning 362 | the installation locations. 363 | 364 | `--no-create' 365 | `-n' 366 | Run the configure checks, but stop before creating any output 367 | files. 368 | 369 | `configure' also accepts some other, not widely useful, options. Run 370 | `configure --help' for more details. 371 | -------------------------------------------------------------------------------- /m4/ax_cxx_compile_stdcxx.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the specified 12 | # version of the C++ standard. If necessary, add switches to CXX and 13 | # CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for 14 | # the respective C++ standard version. 15 | # 16 | # The second argument, if specified, indicates whether you insist on an 17 | # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 18 | # -std=c++11). If neither is specified, you get whatever works, with 19 | # preference for no added switch, and then for an extended mode. 20 | # 21 | # The third argument, if specified 'mandatory' or if left unspecified, 22 | # indicates that baseline support for the specified C++ standard is 23 | # required and that the macro should error out if no mode with that 24 | # support is found. If specified 'optional', then configuration proceeds 25 | # regardless, after defining HAVE_CXX${VERSION} if and only if a 26 | # supporting mode is found. 27 | # 28 | # LICENSE 29 | # 30 | # Copyright (c) 2008 Benjamin Kosnik 31 | # Copyright (c) 2012 Zack Weinberg 32 | # Copyright (c) 2013 Roy Stogner 33 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 34 | # Copyright (c) 2015 Paul Norman 35 | # Copyright (c) 2015 Moritz Klammler 36 | # Copyright (c) 2016, 2018 Krzesimir Nowak 37 | # Copyright (c) 2019 Enji Cooper 38 | # Copyright (c) 2020 Jason Merrill 39 | # Copyright (c) 2021 Jörn Heusipp 40 | # 41 | # Copying and distribution of this file, with or without modification, are 42 | # permitted in any medium without royalty provided the copyright notice 43 | # and this notice are preserved. This file is offered as-is, without any 44 | # warranty. 45 | 46 | #serial 14 47 | 48 | dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 49 | dnl (serial version number 13). 50 | 51 | AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 52 | m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], 53 | [$1], [14], [ax_cxx_compile_alternatives="14 1y"], 54 | [$1], [17], [ax_cxx_compile_alternatives="17 1z"], 55 | [$1], [20], [ax_cxx_compile_alternatives="20"], 56 | [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 57 | m4_if([$2], [], [], 58 | [$2], [ext], [], 59 | [$2], [noext], [], 60 | [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 61 | m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 62 | [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 63 | [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 64 | [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 65 | AC_LANG_PUSH([C++])dnl 66 | ac_success=no 67 | 68 | m4_if([$2], [], [dnl 69 | AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, 70 | ax_cv_cxx_compile_cxx$1, 71 | [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 72 | [ax_cv_cxx_compile_cxx$1=yes], 73 | [ax_cv_cxx_compile_cxx$1=no])]) 74 | if test x$ax_cv_cxx_compile_cxx$1 = xyes; then 75 | ac_success=yes 76 | fi]) 77 | 78 | m4_if([$2], [noext], [], [dnl 79 | if test x$ac_success = xno; then 80 | for alternative in ${ax_cxx_compile_alternatives}; do 81 | switch="-std=gnu++${alternative}" 82 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 83 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 84 | $cachevar, 85 | [ac_save_CXX="$CXX" 86 | CXX="$CXX $switch" 87 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 88 | [eval $cachevar=yes], 89 | [eval $cachevar=no]) 90 | CXX="$ac_save_CXX"]) 91 | if eval test x\$$cachevar = xyes; then 92 | CXX="$CXX $switch" 93 | if test -n "$CXXCPP" ; then 94 | CXXCPP="$CXXCPP $switch" 95 | fi 96 | ac_success=yes 97 | break 98 | fi 99 | done 100 | fi]) 101 | 102 | m4_if([$2], [ext], [], [dnl 103 | if test x$ac_success = xno; then 104 | dnl HP's aCC needs +std=c++11 according to: 105 | dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 106 | dnl Cray's crayCC needs "-h std=c++11" 107 | for alternative in ${ax_cxx_compile_alternatives}; do 108 | for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do 109 | cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 110 | AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 111 | $cachevar, 112 | [ac_save_CXX="$CXX" 113 | CXX="$CXX $switch" 114 | AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 115 | [eval $cachevar=yes], 116 | [eval $cachevar=no]) 117 | CXX="$ac_save_CXX"]) 118 | if eval test x\$$cachevar = xyes; then 119 | CXX="$CXX $switch" 120 | if test -n "$CXXCPP" ; then 121 | CXXCPP="$CXXCPP $switch" 122 | fi 123 | ac_success=yes 124 | break 125 | fi 126 | done 127 | if test x$ac_success = xyes; then 128 | break 129 | fi 130 | done 131 | fi]) 132 | AC_LANG_POP([C++]) 133 | if test x$ax_cxx_compile_cxx$1_required = xtrue; then 134 | if test x$ac_success = xno; then 135 | AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 136 | fi 137 | fi 138 | if test x$ac_success = xno; then 139 | HAVE_CXX$1=0 140 | AC_MSG_NOTICE([No compiler with C++$1 support was found]) 141 | else 142 | HAVE_CXX$1=1 143 | AC_DEFINE(HAVE_CXX$1,1, 144 | [define if the compiler supports basic C++$1 syntax]) 145 | fi 146 | AC_SUBST(HAVE_CXX$1) 147 | ]) 148 | 149 | 150 | dnl Test body for checking C++11 support 151 | 152 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 153 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 154 | ) 155 | 156 | dnl Test body for checking C++14 support 157 | 158 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 159 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 160 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 161 | ) 162 | 163 | dnl Test body for checking C++17 support 164 | 165 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], 166 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 167 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 168 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 169 | ) 170 | 171 | dnl Test body for checking C++20 support 172 | 173 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], 174 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 175 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 176 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 177 | _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 178 | ) 179 | 180 | 181 | dnl Tests for new features in C++11 182 | 183 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 184 | 185 | // If the compiler admits that it is not ready for C++11, why torture it? 186 | // Hopefully, this will speed up the test. 187 | 188 | #ifndef __cplusplus 189 | 190 | #error "This is not a C++ compiler" 191 | 192 | #elif __cplusplus < 201103L 193 | 194 | #error "This is not a C++11 compiler" 195 | 196 | #else 197 | 198 | namespace cxx11 199 | { 200 | 201 | namespace test_static_assert 202 | { 203 | 204 | template 205 | struct check 206 | { 207 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 208 | }; 209 | 210 | } 211 | 212 | namespace test_final_override 213 | { 214 | 215 | struct Base 216 | { 217 | virtual ~Base() {} 218 | virtual void f() {} 219 | }; 220 | 221 | struct Derived : public Base 222 | { 223 | virtual ~Derived() override {} 224 | virtual void f() override {} 225 | }; 226 | 227 | } 228 | 229 | namespace test_double_right_angle_brackets 230 | { 231 | 232 | template < typename T > 233 | struct check {}; 234 | 235 | typedef check single_type; 236 | typedef check> double_type; 237 | typedef check>> triple_type; 238 | typedef check>>> quadruple_type; 239 | 240 | } 241 | 242 | namespace test_decltype 243 | { 244 | 245 | int 246 | f() 247 | { 248 | int a = 1; 249 | decltype(a) b = 2; 250 | return a + b; 251 | } 252 | 253 | } 254 | 255 | namespace test_type_deduction 256 | { 257 | 258 | template < typename T1, typename T2 > 259 | struct is_same 260 | { 261 | static const bool value = false; 262 | }; 263 | 264 | template < typename T > 265 | struct is_same 266 | { 267 | static const bool value = true; 268 | }; 269 | 270 | template < typename T1, typename T2 > 271 | auto 272 | add(T1 a1, T2 a2) -> decltype(a1 + a2) 273 | { 274 | return a1 + a2; 275 | } 276 | 277 | int 278 | test(const int c, volatile int v) 279 | { 280 | static_assert(is_same::value == true, ""); 281 | static_assert(is_same::value == false, ""); 282 | static_assert(is_same::value == false, ""); 283 | auto ac = c; 284 | auto av = v; 285 | auto sumi = ac + av + 'x'; 286 | auto sumf = ac + av + 1.0; 287 | static_assert(is_same::value == true, ""); 288 | static_assert(is_same::value == true, ""); 289 | static_assert(is_same::value == true, ""); 290 | static_assert(is_same::value == false, ""); 291 | static_assert(is_same::value == true, ""); 292 | return (sumf > 0.0) ? sumi : add(c, v); 293 | } 294 | 295 | } 296 | 297 | namespace test_noexcept 298 | { 299 | 300 | int f() { return 0; } 301 | int g() noexcept { return 0; } 302 | 303 | static_assert(noexcept(f()) == false, ""); 304 | static_assert(noexcept(g()) == true, ""); 305 | 306 | } 307 | 308 | namespace test_constexpr 309 | { 310 | 311 | template < typename CharT > 312 | unsigned long constexpr 313 | strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 314 | { 315 | return *s ? strlen_c_r(s + 1, acc + 1) : acc; 316 | } 317 | 318 | template < typename CharT > 319 | unsigned long constexpr 320 | strlen_c(const CharT *const s) noexcept 321 | { 322 | return strlen_c_r(s, 0UL); 323 | } 324 | 325 | static_assert(strlen_c("") == 0UL, ""); 326 | static_assert(strlen_c("1") == 1UL, ""); 327 | static_assert(strlen_c("example") == 7UL, ""); 328 | static_assert(strlen_c("another\0example") == 7UL, ""); 329 | 330 | } 331 | 332 | namespace test_rvalue_references 333 | { 334 | 335 | template < int N > 336 | struct answer 337 | { 338 | static constexpr int value = N; 339 | }; 340 | 341 | answer<1> f(int&) { return answer<1>(); } 342 | answer<2> f(const int&) { return answer<2>(); } 343 | answer<3> f(int&&) { return answer<3>(); } 344 | 345 | void 346 | test() 347 | { 348 | int i = 0; 349 | const int c = 0; 350 | static_assert(decltype(f(i))::value == 1, ""); 351 | static_assert(decltype(f(c))::value == 2, ""); 352 | static_assert(decltype(f(0))::value == 3, ""); 353 | } 354 | 355 | } 356 | 357 | namespace test_uniform_initialization 358 | { 359 | 360 | struct test 361 | { 362 | static const int zero {}; 363 | static const int one {1}; 364 | }; 365 | 366 | static_assert(test::zero == 0, ""); 367 | static_assert(test::one == 1, ""); 368 | 369 | } 370 | 371 | namespace test_lambdas 372 | { 373 | 374 | void 375 | test1() 376 | { 377 | auto lambda1 = [](){}; 378 | auto lambda2 = lambda1; 379 | lambda1(); 380 | lambda2(); 381 | } 382 | 383 | int 384 | test2() 385 | { 386 | auto a = [](int i, int j){ return i + j; }(1, 2); 387 | auto b = []() -> int { return '0'; }(); 388 | auto c = [=](){ return a + b; }(); 389 | auto d = [&](){ return c; }(); 390 | auto e = [a, &b](int x) mutable { 391 | const auto identity = [](int y){ return y; }; 392 | for (auto i = 0; i < a; ++i) 393 | a += b--; 394 | return x + identity(a + b); 395 | }(0); 396 | return a + b + c + d + e; 397 | } 398 | 399 | int 400 | test3() 401 | { 402 | const auto nullary = [](){ return 0; }; 403 | const auto unary = [](int x){ return x; }; 404 | using nullary_t = decltype(nullary); 405 | using unary_t = decltype(unary); 406 | const auto higher1st = [](nullary_t f){ return f(); }; 407 | const auto higher2nd = [unary](nullary_t f1){ 408 | return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 409 | }; 410 | return higher1st(nullary) + higher2nd(nullary)(unary); 411 | } 412 | 413 | } 414 | 415 | namespace test_variadic_templates 416 | { 417 | 418 | template 419 | struct sum; 420 | 421 | template 422 | struct sum 423 | { 424 | static constexpr auto value = N0 + sum::value; 425 | }; 426 | 427 | template <> 428 | struct sum<> 429 | { 430 | static constexpr auto value = 0; 431 | }; 432 | 433 | static_assert(sum<>::value == 0, ""); 434 | static_assert(sum<1>::value == 1, ""); 435 | static_assert(sum<23>::value == 23, ""); 436 | static_assert(sum<1, 2>::value == 3, ""); 437 | static_assert(sum<5, 5, 11>::value == 21, ""); 438 | static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 439 | 440 | } 441 | 442 | // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 443 | // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 444 | // because of this. 445 | namespace test_template_alias_sfinae 446 | { 447 | 448 | struct foo {}; 449 | 450 | template 451 | using member = typename T::member_type; 452 | 453 | template 454 | void func(...) {} 455 | 456 | template 457 | void func(member*) {} 458 | 459 | void test(); 460 | 461 | void test() { func(0); } 462 | 463 | } 464 | 465 | } // namespace cxx11 466 | 467 | #endif // __cplusplus >= 201103L 468 | 469 | ]]) 470 | 471 | 472 | dnl Tests for new features in C++14 473 | 474 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 475 | 476 | // If the compiler admits that it is not ready for C++14, why torture it? 477 | // Hopefully, this will speed up the test. 478 | 479 | #ifndef __cplusplus 480 | 481 | #error "This is not a C++ compiler" 482 | 483 | #elif __cplusplus < 201402L 484 | 485 | #error "This is not a C++14 compiler" 486 | 487 | #else 488 | 489 | namespace cxx14 490 | { 491 | 492 | namespace test_polymorphic_lambdas 493 | { 494 | 495 | int 496 | test() 497 | { 498 | const auto lambda = [](auto&&... args){ 499 | const auto istiny = [](auto x){ 500 | return (sizeof(x) == 1UL) ? 1 : 0; 501 | }; 502 | const int aretiny[] = { istiny(args)... }; 503 | return aretiny[0]; 504 | }; 505 | return lambda(1, 1L, 1.0f, '1'); 506 | } 507 | 508 | } 509 | 510 | namespace test_binary_literals 511 | { 512 | 513 | constexpr auto ivii = 0b0000000000101010; 514 | static_assert(ivii == 42, "wrong value"); 515 | 516 | } 517 | 518 | namespace test_generalized_constexpr 519 | { 520 | 521 | template < typename CharT > 522 | constexpr unsigned long 523 | strlen_c(const CharT *const s) noexcept 524 | { 525 | auto length = 0UL; 526 | for (auto p = s; *p; ++p) 527 | ++length; 528 | return length; 529 | } 530 | 531 | static_assert(strlen_c("") == 0UL, ""); 532 | static_assert(strlen_c("x") == 1UL, ""); 533 | static_assert(strlen_c("test") == 4UL, ""); 534 | static_assert(strlen_c("another\0test") == 7UL, ""); 535 | 536 | } 537 | 538 | namespace test_lambda_init_capture 539 | { 540 | 541 | int 542 | test() 543 | { 544 | auto x = 0; 545 | const auto lambda1 = [a = x](int b){ return a + b; }; 546 | const auto lambda2 = [a = lambda1(x)](){ return a; }; 547 | return lambda2(); 548 | } 549 | 550 | } 551 | 552 | namespace test_digit_separators 553 | { 554 | 555 | constexpr auto ten_million = 100'000'000; 556 | static_assert(ten_million == 100000000, ""); 557 | 558 | } 559 | 560 | namespace test_return_type_deduction 561 | { 562 | 563 | auto f(int& x) { return x; } 564 | decltype(auto) g(int& x) { return x; } 565 | 566 | template < typename T1, typename T2 > 567 | struct is_same 568 | { 569 | static constexpr auto value = false; 570 | }; 571 | 572 | template < typename T > 573 | struct is_same 574 | { 575 | static constexpr auto value = true; 576 | }; 577 | 578 | int 579 | test() 580 | { 581 | auto x = 0; 582 | static_assert(is_same::value, ""); 583 | static_assert(is_same::value, ""); 584 | return x; 585 | } 586 | 587 | } 588 | 589 | } // namespace cxx14 590 | 591 | #endif // __cplusplus >= 201402L 592 | 593 | ]]) 594 | 595 | 596 | dnl Tests for new features in C++17 597 | 598 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ 599 | 600 | // If the compiler admits that it is not ready for C++17, why torture it? 601 | // Hopefully, this will speed up the test. 602 | 603 | #ifndef __cplusplus 604 | 605 | #error "This is not a C++ compiler" 606 | 607 | #elif __cplusplus < 201703L 608 | 609 | #error "This is not a C++17 compiler" 610 | 611 | #else 612 | 613 | #include 614 | #include 615 | #include 616 | 617 | namespace cxx17 618 | { 619 | 620 | namespace test_constexpr_lambdas 621 | { 622 | 623 | constexpr int foo = [](){return 42;}(); 624 | 625 | } 626 | 627 | namespace test::nested_namespace::definitions 628 | { 629 | 630 | } 631 | 632 | namespace test_fold_expression 633 | { 634 | 635 | template 636 | int multiply(Args... args) 637 | { 638 | return (args * ... * 1); 639 | } 640 | 641 | template 642 | bool all(Args... args) 643 | { 644 | return (args && ...); 645 | } 646 | 647 | } 648 | 649 | namespace test_extended_static_assert 650 | { 651 | 652 | static_assert (true); 653 | 654 | } 655 | 656 | namespace test_auto_brace_init_list 657 | { 658 | 659 | auto foo = {5}; 660 | auto bar {5}; 661 | 662 | static_assert(std::is_same, decltype(foo)>::value); 663 | static_assert(std::is_same::value); 664 | } 665 | 666 | namespace test_typename_in_template_template_parameter 667 | { 668 | 669 | template typename X> struct D; 670 | 671 | } 672 | 673 | namespace test_fallthrough_nodiscard_maybe_unused_attributes 674 | { 675 | 676 | int f1() 677 | { 678 | return 42; 679 | } 680 | 681 | [[nodiscard]] int f2() 682 | { 683 | [[maybe_unused]] auto unused = f1(); 684 | 685 | switch (f1()) 686 | { 687 | case 17: 688 | f1(); 689 | [[fallthrough]]; 690 | case 42: 691 | f1(); 692 | } 693 | return f1(); 694 | } 695 | 696 | } 697 | 698 | namespace test_extended_aggregate_initialization 699 | { 700 | 701 | struct base1 702 | { 703 | int b1, b2 = 42; 704 | }; 705 | 706 | struct base2 707 | { 708 | base2() { 709 | b3 = 42; 710 | } 711 | int b3; 712 | }; 713 | 714 | struct derived : base1, base2 715 | { 716 | int d; 717 | }; 718 | 719 | derived d1 {{1, 2}, {}, 4}; // full initialization 720 | derived d2 {{}, {}, 4}; // value-initialized bases 721 | 722 | } 723 | 724 | namespace test_general_range_based_for_loop 725 | { 726 | 727 | struct iter 728 | { 729 | int i; 730 | 731 | int& operator* () 732 | { 733 | return i; 734 | } 735 | 736 | const int& operator* () const 737 | { 738 | return i; 739 | } 740 | 741 | iter& operator++() 742 | { 743 | ++i; 744 | return *this; 745 | } 746 | }; 747 | 748 | struct sentinel 749 | { 750 | int i; 751 | }; 752 | 753 | bool operator== (const iter& i, const sentinel& s) 754 | { 755 | return i.i == s.i; 756 | } 757 | 758 | bool operator!= (const iter& i, const sentinel& s) 759 | { 760 | return !(i == s); 761 | } 762 | 763 | struct range 764 | { 765 | iter begin() const 766 | { 767 | return {0}; 768 | } 769 | 770 | sentinel end() const 771 | { 772 | return {5}; 773 | } 774 | }; 775 | 776 | void f() 777 | { 778 | range r {}; 779 | 780 | for (auto i : r) 781 | { 782 | [[maybe_unused]] auto v = i; 783 | } 784 | } 785 | 786 | } 787 | 788 | namespace test_lambda_capture_asterisk_this_by_value 789 | { 790 | 791 | struct t 792 | { 793 | int i; 794 | int foo() 795 | { 796 | return [*this]() 797 | { 798 | return i; 799 | }(); 800 | } 801 | }; 802 | 803 | } 804 | 805 | namespace test_enum_class_construction 806 | { 807 | 808 | enum class byte : unsigned char 809 | {}; 810 | 811 | byte foo {42}; 812 | 813 | } 814 | 815 | namespace test_constexpr_if 816 | { 817 | 818 | template 819 | int f () 820 | { 821 | if constexpr(cond) 822 | { 823 | return 13; 824 | } 825 | else 826 | { 827 | return 42; 828 | } 829 | } 830 | 831 | } 832 | 833 | namespace test_selection_statement_with_initializer 834 | { 835 | 836 | int f() 837 | { 838 | return 13; 839 | } 840 | 841 | int f2() 842 | { 843 | if (auto i = f(); i > 0) 844 | { 845 | return 3; 846 | } 847 | 848 | switch (auto i = f(); i + 4) 849 | { 850 | case 17: 851 | return 2; 852 | 853 | default: 854 | return 1; 855 | } 856 | } 857 | 858 | } 859 | 860 | namespace test_template_argument_deduction_for_class_templates 861 | { 862 | 863 | template 864 | struct pair 865 | { 866 | pair (T1 p1, T2 p2) 867 | : m1 {p1}, 868 | m2 {p2} 869 | {} 870 | 871 | T1 m1; 872 | T2 m2; 873 | }; 874 | 875 | void f() 876 | { 877 | [[maybe_unused]] auto p = pair{13, 42u}; 878 | } 879 | 880 | } 881 | 882 | namespace test_non_type_auto_template_parameters 883 | { 884 | 885 | template 886 | struct B 887 | {}; 888 | 889 | B<5> b1; 890 | B<'a'> b2; 891 | 892 | } 893 | 894 | namespace test_structured_bindings 895 | { 896 | 897 | int arr[2] = { 1, 2 }; 898 | std::pair pr = { 1, 2 }; 899 | 900 | auto f1() -> int(&)[2] 901 | { 902 | return arr; 903 | } 904 | 905 | auto f2() -> std::pair& 906 | { 907 | return pr; 908 | } 909 | 910 | struct S 911 | { 912 | int x1 : 2; 913 | volatile double y1; 914 | }; 915 | 916 | S f3() 917 | { 918 | return {}; 919 | } 920 | 921 | auto [ x1, y1 ] = f1(); 922 | auto& [ xr1, yr1 ] = f1(); 923 | auto [ x2, y2 ] = f2(); 924 | auto& [ xr2, yr2 ] = f2(); 925 | const auto [ x3, y3 ] = f3(); 926 | 927 | } 928 | 929 | namespace test_exception_spec_type_system 930 | { 931 | 932 | struct Good {}; 933 | struct Bad {}; 934 | 935 | void g1() noexcept; 936 | void g2(); 937 | 938 | template 939 | Bad 940 | f(T*, T*); 941 | 942 | template 943 | Good 944 | f(T1*, T2*); 945 | 946 | static_assert (std::is_same_v); 947 | 948 | } 949 | 950 | namespace test_inline_variables 951 | { 952 | 953 | template void f(T) 954 | {} 955 | 956 | template inline T g(T) 957 | { 958 | return T{}; 959 | } 960 | 961 | template<> inline void f<>(int) 962 | {} 963 | 964 | template<> int g<>(int) 965 | { 966 | return 5; 967 | } 968 | 969 | } 970 | 971 | } // namespace cxx17 972 | 973 | #endif // __cplusplus < 201703L 974 | 975 | ]]) 976 | 977 | 978 | dnl Tests for new features in C++20 979 | 980 | m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ 981 | 982 | #ifndef __cplusplus 983 | 984 | #error "This is not a C++ compiler" 985 | 986 | #elif __cplusplus < 202002L 987 | 988 | #error "This is not a C++20 compiler" 989 | 990 | #else 991 | 992 | #include 993 | 994 | namespace cxx20 995 | { 996 | 997 | // As C++20 supports feature test macros in the standard, there is no 998 | // immediate need to actually test for feature availability on the 999 | // Autoconf side. 1000 | 1001 | } // namespace cxx20 1002 | 1003 | #endif // __cplusplus < 202002L 1004 | 1005 | ]]) 1006 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################### 3 | # Copyright (c) 2014-2023 libbitcoin-client developers (see COPYING). 4 | # 5 | # GENERATED SOURCE CODE, DO NOT EDIT EXCEPT EXPERIMENTALLY 6 | # 7 | ############################################################################### 8 | # Script to build and install libbitcoin-client. 9 | # 10 | # Script options: 11 | # --with-icu Compile with International Components for Unicode. 12 | # Since the addition of BIP-39 and later BIP-38 13 | # support, libbitcoin conditionally incorporates ICU 14 | # to provide BIP-38 and BIP-39 passphrase 15 | # normalization features. Currently 16 | # libbitcoin-explorer is the only other library that 17 | # accesses this feature, so if you do not intend to 18 | # use passphrase normalization this dependency can 19 | # be avoided. 20 | # --build-icu Builds ICU libraries. 21 | # --build-boost Builds Boost libraries. 22 | # --build-zmq Builds ZeroMQ libraries. 23 | # --build-dir= Location of downloaded and intermediate files. 24 | # --prefix= Library install location (defaults to /usr/local). 25 | # --disable-shared Disables shared library builds. 26 | # --disable-static Disables static library builds. 27 | # --verbose Display verbose output (defaults to quiet on called tooling). 28 | # --help Display usage, overriding script execution. 29 | # 30 | # Verified on Ubuntu 14.04, requires gcc-4.8 or newer. 31 | # Verified on OSX 10.10, using MacPorts and Homebrew repositories, requires 32 | # Apple LLVM version 6.0 (clang-600.0.54) (based on LLVM 3.5svn) or newer. 33 | # This script does not like spaces in the --prefix or --build-dir, sorry. 34 | # Values (e.g. yes|no) in the '--disable-' options are not supported. 35 | # All command line options are passed to 'configure' of each repo, with 36 | # the exception of the --build- options, which are for the script only. 37 | # Depending on the caller's permission to the --prefix or --build-dir 38 | # directory, the script may need to be sudo'd. 39 | 40 | # Define constants. 41 | #============================================================================== 42 | # Sentinel for comparison of sequential build. 43 | #------------------------------------------------------------------------------ 44 | SEQUENTIAL=1 45 | 46 | # Git clone parameters. 47 | #------------------------------------------------------------------------------ 48 | if [[ $GIT_CLONE_PARAMS ]]; then 49 | display_message "Using shell-defined GIT_CLONE_PARAMS value." 50 | else 51 | GIT_CLONE_PARAMS="--depth 1 --single-branch" 52 | fi 53 | 54 | # The default build directory. 55 | #------------------------------------------------------------------------------ 56 | BUILD_DIR="build-libbitcoin-client" 57 | 58 | PRESUMED_CI_PROJECT_PATH=$(pwd) 59 | 60 | # ICU archive. 61 | #------------------------------------------------------------------------------ 62 | ICU_URL="https://github.com/unicode-org/icu/releases/download/release-55-2/icu4c-55_2-src.tgz" 63 | ICU_ARCHIVE="icu4c-55_2-src.tgz" 64 | 65 | # ZMQ archive. 66 | #------------------------------------------------------------------------------ 67 | ZMQ_URL="https://github.com/zeromq/libzmq/releases/download/v4.3.4/zeromq-4.3.4.tar.gz" 68 | ZMQ_ARCHIVE="zeromq-4.3.4.tar.gz" 69 | 70 | # Boost archive. 71 | #------------------------------------------------------------------------------ 72 | BOOST_URL="http://downloads.sourceforge.net/project/boost/boost/1.78.0/boost_1_78_0.tar.bz2" 73 | BOOST_ARCHIVE="boost_1_78_0.tar.bz2" 74 | 75 | 76 | # Define utility functions. 77 | #============================================================================== 78 | configure_links() 79 | { 80 | # Configure dynamic linker run-time bindings when installing to system. 81 | if [[ ($OS == Linux) && ($PREFIX == "/usr/local") ]]; then 82 | ldconfig 83 | fi 84 | } 85 | 86 | configure_options() 87 | { 88 | display_message "configure options:" 89 | for OPTION in "$@"; do 90 | if [[ $OPTION ]]; then 91 | display_message "$OPTION" 92 | fi 93 | done 94 | 95 | ./configure "$@" 96 | } 97 | 98 | create_directory() 99 | { 100 | local DIRECTORY="$1" 101 | 102 | rm -rf "$DIRECTORY" 103 | mkdir "$DIRECTORY" 104 | } 105 | 106 | display_heading_message() 107 | { 108 | printf "\n********************** %s **********************\n" "$@" 109 | } 110 | 111 | display_message() 112 | { 113 | printf "%s\n" "$@" 114 | } 115 | 116 | display_error() 117 | { 118 | >&2 printf "%s\n" "$@" 119 | } 120 | 121 | initialize_git() 122 | { 123 | display_heading_message "Initialize git" 124 | 125 | # Initialize git repository at the root of the current directory. 126 | git init 127 | git config user.name anonymous 128 | } 129 | 130 | # make_project_directory project_name jobs [configure_options] 131 | make_project_directory() 132 | { 133 | local PROJ_NAME=$1 134 | local JOBS=$2 135 | local TEST=$3 136 | shift 3 137 | 138 | push_directory "$PROJ_NAME" 139 | local PROJ_CONFIG_DIR 140 | PROJ_CONFIG_DIR=$(pwd) 141 | 142 | ./autogen.sh 143 | 144 | configure_options "$@" 145 | make_jobs "$JOBS" 146 | 147 | if [[ $TEST == true ]]; then 148 | make_tests "$JOBS" 149 | fi 150 | 151 | make install 152 | configure_links 153 | pop_directory 154 | } 155 | 156 | # make_jobs jobs [make_options] 157 | make_jobs() 158 | { 159 | local JOBS=$1 160 | shift 1 161 | 162 | VERBOSITY="" 163 | if [[ DISPLAY_VERBOSE ]]; then 164 | VERBOSITY="VERBOSE=1" 165 | fi 166 | 167 | SEQUENTIAL=1 168 | # Avoid setting -j1 (causes problems on single threaded systems [TRAVIS]). 169 | if [[ $JOBS > $SEQUENTIAL ]]; then 170 | make -j"$JOBS" "$@" $VERBOSITY 171 | else 172 | make "$@" $VERBOSITY 173 | fi 174 | } 175 | 176 | # make_tests jobs 177 | make_tests() 178 | { 179 | local JOBS=$1 180 | 181 | disable_exit_on_error 182 | 183 | # Build and run unit tests relative to the primary directory. 184 | # VERBOSE=1 ensures test runner output sent to console (gcc). 185 | make_jobs "$JOBS" check "VERBOSE=1" 186 | local RESULT=$? 187 | 188 | # Test runners emit to the test.log file. 189 | if [[ -e "test.log" ]]; then 190 | cat "test.log" 191 | fi 192 | 193 | if [[ $RESULT -ne 0 ]]; then 194 | exit $RESULT 195 | fi 196 | 197 | enable_exit_on_error 198 | } 199 | 200 | pop_directory() 201 | { 202 | popd >/dev/null 203 | } 204 | 205 | push_directory() 206 | { 207 | local DIRECTORY="$1" 208 | 209 | pushd "$DIRECTORY" >/dev/null 210 | } 211 | 212 | enable_exit_on_error() 213 | { 214 | set -e 215 | } 216 | 217 | disable_exit_on_error() 218 | { 219 | set +e 220 | } 221 | 222 | display_help() 223 | { 224 | display_message "Usage: ./install.sh [OPTION]..." 225 | display_message "Manage the installation of libbitcoin-client." 226 | display_message "Script options:" 227 | display_message " --with-icu Compile with International Components for Unicode." 228 | display_message " Since the addition of BIP-39 and later BIP-38 " 229 | display_message " support, libbitcoin conditionally incorporates ICU " 230 | display_message " to provide BIP-38 and BIP-39 passphrase " 231 | display_message " normalization features. Currently " 232 | display_message " libbitcoin-explorer is the only other library that " 233 | display_message " accesses this feature, so if you do not intend to " 234 | display_message " use passphrase normalization this dependency can " 235 | display_message " be avoided." 236 | display_message " --build-icu Builds ICU libraries." 237 | display_message " --build-boost Builds Boost libraries." 238 | display_message " --build-zmq Build ZeroMQ libraries." 239 | display_message " --build-dir= Location of downloaded and intermediate files." 240 | display_message " --prefix= Library install location (defaults to /usr/local)." 241 | display_message " --disable-shared Disables shared library builds." 242 | display_message " --disable-static Disables static library builds." 243 | display_message " --help Display usage, overriding script execution." 244 | display_message "" 245 | display_message "All unrecognized options provided shall be passed as configuration options for " 246 | display_message "all dependencies." 247 | } 248 | 249 | # Define environment initialization functions 250 | #============================================================================== 251 | parse_command_line_options() 252 | { 253 | for OPTION in "$@"; do 254 | case $OPTION in 255 | # Standard script options. 256 | (--help) DISPLAY_HELP="yes";; 257 | (--verbose) DISPLAY_VERBOSE="yes";; 258 | 259 | # Standard build options. 260 | (--prefix=*) PREFIX="${OPTION#*=}";; 261 | (--disable-shared) DISABLE_SHARED="yes";; 262 | (--disable-static) DISABLE_STATIC="yes";; 263 | 264 | # Common project options. 265 | (--with-icu) WITH_ICU="yes";; 266 | 267 | # Custom build options (in the form of --build-