From 600c414c6fcc48573bf6c125b0b27c0d362bd68f Mon Sep 17 00:00:00 2001 From: l2xl Date: Thu, 1 Jun 2023 20:24:02 +0300 Subject: [PATCH 01/59] Migrate inscribeit module to separate repo utxord-wallet --- Makefile.am | 41 +- build-aux/m4/ax_subdirs_configure.m4 | 12 +- configure.ac | 205 ++--- contrib/Makefile.am | 3 +- src/Makefile.am | 12 - src/api/Makefile.am | 21 +- src/api/chain_api.hpp | 4 +- src/api/exechelper.cpp | 2 +- src/api/exechelper.hpp | 2 +- src/common/Makefile.am | 18 +- src/core/Makefile.am | 14 +- src/inscribeit/Makefile.am | 23 - src/inscribeit/contract_builder.cpp | 57 -- src/inscribeit/contract_builder.hpp | 54 -- src/inscribeit/contract_error.hpp | 70 -- src/inscribeit/create_inscription.cpp | 580 ------------- src/inscribeit/create_inscription.hpp | 128 --- src/inscribeit/swap_inscription.cpp | 890 -------------------- src/inscribeit/swap_inscription.hpp | 163 ---- src/python_binding/Makefile.am | 45 - src/python_binding/Readme.md | 230 ----- src/python_binding/__init__.py | 2 - src/python_binding/l15-core-pybind.i | 115 --- src/service/Makefile.am | 18 +- src/tools/Makefile.am | 6 +- src/wasm_binding/Makefile.am | 42 - src/wasm_binding/inscribeit.idl | 83 -- src/wasm_binding/l15.cpp | 71 -- test/Makefile.am | 40 +- test/core/Makefile.am | 38 +- test/core/test_node.cpp | 85 +- test/core/test_taproot.cpp | 108 +-- test/core/test_taptree.cpp | 2 +- test/inscribeit/Makefile.am | 48 -- test/inscribeit/test_create_inscription.cpp | 264 ------ test/inscribeit/test_signing.cpp | 41 - test/inscribeit/test_swap_inscription.cpp | 401 --------- test/p2p/Makefile.am | 35 +- test/python_module/exception_test.py | 32 - test/service/Makefile.am | 38 +- test/test_case_wrapper.hpp | 15 +- 41 files changed, 308 insertions(+), 3750 deletions(-) delete mode 100644 src/inscribeit/Makefile.am delete mode 100644 src/inscribeit/contract_builder.cpp delete mode 100644 src/inscribeit/contract_builder.hpp delete mode 100644 src/inscribeit/contract_error.hpp delete mode 100644 src/inscribeit/create_inscription.cpp delete mode 100644 src/inscribeit/create_inscription.hpp delete mode 100644 src/inscribeit/swap_inscription.cpp delete mode 100644 src/inscribeit/swap_inscription.hpp delete mode 100644 src/python_binding/Makefile.am delete mode 100644 src/python_binding/Readme.md delete mode 100644 src/python_binding/__init__.py delete mode 100644 src/python_binding/l15-core-pybind.i delete mode 100644 src/wasm_binding/Makefile.am delete mode 100644 src/wasm_binding/inscribeit.idl delete mode 100644 src/wasm_binding/l15.cpp delete mode 100644 test/inscribeit/Makefile.am delete mode 100644 test/inscribeit/test_create_inscription.cpp delete mode 100644 test/inscribeit/test_signing.cpp delete mode 100644 test/inscribeit/test_swap_inscription.cpp delete mode 100644 test/python_module/exception_test.py diff --git a/Makefile.am b/Makefile.am index 0ae60ee..68ad2bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,21 +1,25 @@ ACLOCAL_AMFLAGS = -I build-aux/m4 -SUBDIRS = contrib node src test +SUBDIRS = contrib $(NODE_PATH) src test + +if BUILD_SECP256K1 +SUBDIRS += $(SECP256K1_PATH) +endif AM_CPPFLAGS = \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/core \ - -I$(top_srcdir)/contrib/secp256k1/include \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/contrib/cli11 \ -I$(top_srcdir)/contrib/cex \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support -AM_LDFLAGS=-L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto +AM_LDFLAGS=-L$(top_builddir)/$(NODE_PATH)/src -L$(top_builddir)/$(NODE_PATH)/src/crypto L15_LIBS = @@ -30,21 +34,12 @@ endif L15_LIBS += \ $(top_builddir)/src/core/libl15-core.la \ $(top_builddir)/src/common/libl15-common.la \ -$(top_builddir)/node/src/libbitcoinconsensus.la \ -$(top_builddir)/contrib/secp256k1/libsecp256k1.la \ -$(top_builddir)/node/src/libunivalue.la +$(top_builddir)/$(NODE_PATH)/src/libbitcoinconsensus.la \ +$(top_builddir)/$(NODE_PATH)/src/libunivalue.la \ +$(top_builddir)/$(SECP256K1_PATH)/libsecp256k1.la #$(top_builddir)/node/src/crypto/libbitcoin_crypto_base.la -if BUILD_INSCRIBEIT - -AM_CPPFLAGS += -I$(top_srcdir)/src/inscribeit - -L15_LIBS += \ -$(top_builddir)/src/inscribeit/libl15-inscribeit.la - -endif - if BUILD_TOOLS AM_CPPFLAGS += \ @@ -52,9 +47,9 @@ AM_CPPFLAGS += \ -I$(top_srcdir)/src/tools L15_LIBS += \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_avx2.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_x86_shani.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_sse41.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_avx2.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_x86_shani.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_sse41.la \ $(BOOST_FILESYSTEM_LIB) bin_PROGRAMS = l15-cli diff --git a/build-aux/m4/ax_subdirs_configure.m4 b/build-aux/m4/ax_subdirs_configure.m4 index 5fb522c..3ce2ae1 100644 --- a/build-aux/m4/ax_subdirs_configure.m4 +++ b/build-aux/m4/ax_subdirs_configure.m4 @@ -259,7 +259,7 @@ AC_DEFUN([AX_SUBDIRS_CONFIGURE], # Options that must be removed. m4_ifnblank([$5], [m4_foreach(opt, [$5], [ax_args=$(echo $ax_args | sed "s,'opt',,") ])]) - AS_VAR_APPEND([ax_args], [" '--srcdir=$ac_srcdir'"]) + AS_VAR_APPEND([ax_args], [" '--srcdir=$ac_abs_srcdir'"]) # Add the subdirectory to the list of target subdirectories. ax_subconfigures="$ax_subconfigures $ax_dir" @@ -297,11 +297,11 @@ AC_DEFUN([AX_SUBDIRS_CONFIGURE], cd "$ax_dir" # Check for guested configure; otherwise get Cygnus style configure. - if test -f "$ac_srcdir/configure.gnu"; then - ax_sub_configure=$ac_srcdir/configure.gnu - elif test -f "$ac_srcdir/configure"; then - ax_sub_configure=$ac_srcdir/configure - elif test -f "$ac_srcdir/configure.in"; then + if test -f "$ac_abs_srcdir/configure.gnu"; then + ax_sub_configure=$ac_abs_srcdir/configure.gnu + elif test -f "$ac_abs_srcdir/configure"; then + ax_sub_configure=$ac_abs_srcdir/configure + elif test -f "$ac_abs_srcdir/configure.in"; then # This should be Cygnus configure. ax_sub_configure=$ac_aux_dir/configure else diff --git a/configure.ac b/configure.ac index 26831f6..1fd99b8 100644 --- a/configure.ac +++ b/configure.ac @@ -36,9 +36,9 @@ fi compiler_name=`basename "$CC"` if test "x$compiler_name" = "xemcc"; then - WITH_EMSCRIPTEN=yes + with_emscripten=yes else - WITH_EMSCRIPTEN=no + with_emscripten=no fi # Checks for programs. @@ -52,18 +52,20 @@ AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory]) default_build_tools=yes default_build_services=yes default_build_apis=yes -default_build_inscribeit=no default_plugin_api=no +default_blockchain_node=node +default_secp256k1=contrib/secp256k1 + dnl Enable Python integrations -AC_ARG_ENABLE([python-module], - [AS_HELP_STRING([--enable-python-module],[Enable API binding module for python (disabled by default)])], +AC_ARG_ENABLE([python-binding], + [AS_HELP_STRING([--enable-python-binding],[Enable API binding module for python (disabled by default)])], [ if test $enableval != no; then default_plugin_api=yes fi ], - [enable_python_module=no]) + [enable_python_binding=no]) AC_ARG_ENABLE([wasm-module], [AS_HELP_STRING([--enable-wasm-module], [Enable plugin API binding for WebAssembly (disabled by default)])], @@ -74,7 +76,7 @@ AC_ARG_ENABLE([wasm-module], ], [enable_wasm_module=no]) -if test "$enable_python_module" = "yes" "$enable_wasm_module" = "yes"; then +if test "$enable_python_module" = "yes" && "$enable_wasm_module" = "yes"; then AC_MSG_ERROR([WebAssembly and Python modules cannot be build simultaneously]) fi @@ -85,7 +87,6 @@ AC_ARG_ENABLE([plugin-api], default_build_tools=no default_build_services=no default_build_apis=no - default_build_inscribeit=yes fi ], [ @@ -93,8 +94,6 @@ AC_ARG_ENABLE([plugin-api], default_build_tools=no default_build_services=no default_build_apis=no - default_build_inscribeit=yes - AC_MSG_NOTICE([default_build_inscribeit: $default_build_inscribeit]) fi enable_plugin_api=$default_plugin_api ]) @@ -124,25 +123,42 @@ AC_ARG_ENABLE([build-tools], [enable_build_tools=$default_build_tools]) -AC_ARG_ENABLE([build-inscribeit], - [AS_HELP_STRING([--enable-build-inscribeit], [Enable inscribeit API build (disabled by default)])], +AC_ARG_ENABLE([build-frost-signer], + [AS_HELP_STRING([--enable-build-frost-signer], [Enable build FROST signer (enabled by default)])], [], - [ - enable_build_inscribeit=$default_build_inscribeit - ]) + [enable_build_frost_signer=no]) + + +AC_ARG_WITH([blockchain-node], + [AS_HELP_STRING([--with-blockchain-node\[=path\]], [Build with blockchain node sources (default = './node')])], + [ + if test $withval = yes; then + with_blockchain_node = $default_blockchain_node + fi + ], + [with_blockchain_node=$default_blockchain_node]) +AC_ARG_WITH([secp256k1], + [AS_HELP_STRING([--with-secp256k1\[=path|node\]], [Build with secp256k1 sources (default = './contrib/secp256k1')])], + [ + if test $withval = yes; then + with_secp256k1 = $default_secp256k1 + fi + ], + [with_secp256k1=$default_secp256k1]) + if test "$enable_plugin_api" = "yes"; then if test "$enable_build_apis" = "yes"; then AC_MSG_ERROR([Cannot enable plugin API with general APIs]) fi fi -if test "$enable_build_services" != "yes"; then - if test "$enable_build_tools" = "yes"; then - AC_MSG_ERROR([Cannot build tools without services]) - fi -fi +#if test "$enable_build_services" != "yes"; then +# if test "$enable_build_tools" = "yes"; then +# AC_MSG_ERROR([Cannot build tools without services]) +# fi +#fi if test "$enable_build_apis" != "yes"; then if test "$enable_build_services" = "yes"; then @@ -153,19 +169,12 @@ fi AM_CONDITIONAL([BUILD_APIS], [test "$enable_build_apis" = "yes"]) AM_CONDITIONAL([BUILD_SERVICES], [test "$enable_build_services" = "yes"]) AM_CONDITIONAL([BUILD_TOOLS], [test "$enable_build_tools" = "yes"]) -AM_CONDITIONAL([BUILD_INSCRIBEIT], [test "$enable_build_inscribeit" = "yes"]) AM_CONDITIONAL([BUILD_PLUGIN_API], [test "$enable_plugin_api" = "yes"]) AM_CONDITIONAL([BUILD_PYTHON_MODULE], [test "$enable_python_module" = "yes"]) AM_CONDITIONAL([BUILD_WASM_MODULE], [test "$enable_wasm_module" = "yes"]) +AM_CONDITIONAL([BUILD_SECP256K1], [test "$with_secp256k1" != "node"]) +AM_CONDITIONAL([BUILD_FROST], [test "$enable_build_frost_signer" = "yes"]) -if test "$enable_python_module" = "yes"; then - AM_PATH_PYTHON([3]) - AC_MSG_NOTICE([python is $PYTHON]) - - AX_PKG_SWIG([], [], [ AC_MSG_ERROR([SWIG is required to build.]) ]) - AX_PYTHON_DEVEL - AX_SWIG_PYTHON -fi dnl Enable debug AC_ARG_ENABLE([debug], @@ -237,6 +246,23 @@ if test "$enable_plugin_api" != "yes"; then AX_ZMQ(,,[AC_MSG_ERROR([libzmq is required, but it was not found in your system])]) fi +if test "$with_blockchain_node" = "no"; then + AC_MSG_ERROR([Cannot build without blockchain node]) +fi +if test "$with_secp256k1" = "no"; then + AC_MSG_ERROR([Cannot build without secp256k1]) +fi + +NODE_PATH=$with_blockchain_node +AC_SUBST(NODE_PATH) + +if test "$with_secp256k1" = "node"; then + SECP256K1_PATH=$NODE_PATH/src/secp256k1 +else + SECP256K1_PATH=$with_secp256k1 +fi +AC_SUBST(SECP256K1_PATH) + # Checks for typedefs, structures, and compiler characteristics. AC_TYPE_INT32_T AC_TYPE_INT64_T @@ -244,8 +270,6 @@ AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T -# Checks for library functions. -AC_CHECK_FUNCS([dup2 memset pow sqrt strtoul strtoull]) AC_CONFIG_FILES([Makefile src/Makefile @@ -267,21 +291,6 @@ if test "$enable_build_apis" = "yes"; then AC_CONFIG_FILES([src/api/Makefile test/core/Makefile]) fi -if test "$enable_build_inscribeit" = "yes"; then - AC_CONFIG_FILES([src/inscribeit/Makefile]) - if test "$enable_build_tools" = "yes"; then - AC_CONFIG_FILES([test/inscribeit/Makefile]) - fi -fi - -if test "$enable_python_module" = "yes"; then - AC_CONFIG_FILES([src/python_binding/Makefile]) -fi - -if test "$enable_wasm_module" = "yes"; then - AC_CONFIG_FILES([src/wasm_binding/Makefile]) -fi - dnl boost's m4 checks do something really nasty: they export these vars. As a dnl result, they leak into subdir's configure and crazy things may happen. dnl Until this is fixed upstream and we've synced, we'll just un-export them. @@ -311,46 +320,49 @@ dnl so that is the reason to use more flexible AX_SUBDIRS_CONFIGURE. dnl Unfortunately AX_SUBDIRS_CONFIGURE does not allow 'autoreconf' be called recursively for all subprojects (just does it for 'configure' script only) dnl so we call 'autoreconf' for the every subproject manually with 'autogen.sh', placed at the source tree root. -if test "$enable_plugin_api" = "yes"; then -AX_SUBDIRS_CONFIGURE( - [node], - [[--disable-shared], [--enable-c++20], - [--with-libs], [--without-sqlite], [--without-bdb], [--without-miniupnpc], [--without-natpmp], - [--without-qrencode], [--without-libmultiprocess], [--without-mpgen], - [--without-zmq], [--without-utils], [--without-daemon], [--without-gui], - [--without-experimental-kernel-lib], - [--disable-wallet], [--disable-usdt], [--disable-upnp-default], [--disable-natpmp-default], - [--disable-tests], [--disable-gui-tests], [--disable-bench], [--disable-extended-functional-tests], - [--disable-fuzz], [--disable-fuzz-binary], [--disable-asm], [--disable-multiprocess], [--disable-external-signer], - [--disable-experimental-util-chainstate], [--disable-hardening]], - [[--disable-tests], [--disable-bench], [--with-pic]], - [[--disable-examples]], - []) +AS_IF([test "$enable_plugin_api" = "yes"], [btc_sqlite=--without-sqlite], + [btc_sqlite=--with-sqlite]) -AX_SUBDIRS_CONFIGURE( - [contrib/secp256k1], - [[--enable-static], [--disable-shared], [--enable-experimental], [--enable-module-schnorrsig]], - [[--disable-tests], [--disable-benchmark], [--disable-examples], [--with-pic]], - [], - [[--disable-bench]]) +AS_IF([test "$enable_plugin_api" = "yes"], [btc_cli=--disable-util-cli], + [btc_cli=--enable-util-cli]) +AS_IF([test "$enable_plugin_api" = "yes"], [btc_utils=--without-utils], + [btc_utils=--with-utils]) -else +AS_IF([test "$enable_plugin_api" = "yes"], [btc_daemon=--without-daemon], + [btc_daemon=--with-daemon]) + +AS_IF([test "$with_emscripten" = "yes"], [btc_asm=--disable-asm], + [btc_asm=--enable-asm]) + +AS_IF([test "x$with_zmq" = "xyes"], [btc_zmq=--with-zmq], + [test "x$with_zmq" != "xno"], [btc_zmq="--with-zmq=$with_zmq"], + [btc_zmq=--without-zmq]) -AX_SUBDIRS_CONFIGURE( - [node], - [[--enable-static], [--disable-shared], [--enable-c++20], [--disable-hardening], [--disable-multiprocess], [--with-gui=no], [--with-incompatible-bdb], [--with-tests=no]], - [[--disable-tests], [--disable-bench], [--with-zmq], [--with-pic]], - [], - []) AX_SUBDIRS_CONFIGURE( - [contrib/secp256k1], - [[--enable-static], [--disable-shared], [--enable-experimental], [--enable-module-musig], [--enable-module-schnorrsig], [--enable-module-frost], [--enable-module-recovery]], - [[--disable-tests], [--disable-benchmark], [--enable-examples], [--with-pic]], - [], + [$NODE_PATH], + [[--disable-shared], [--enable-c++20], [--without-gui], + [--with-libs], [--without-bdb], [$btc_sqlite], [$btc_zmq], + [--without-libmultiprocess], [--without-mpgen], + [$btc_utils], [$btc_cli], [$btc_daemon], + [--with-experimental-kernel-lib],[--disable-experimental-util-chainstate], + [--disable-multiprocess], [--disable-external-signer], + [--disable-usdt], + [--disable-tests], [--disable-gui-tests], [--disable-bench], [--disable-extended-functional-tests], + [--disable-fuzz], [--disable-fuzz-binary], + [$btc_asm]], + [[--disable-tests], [--disable-bench], [--with-pic]], + [[--disable-examples]], + [[--with-blockchain-node], [--with-secp256k1], [--enable-build-tools], [--enable-build-services], [--enable-build-apis]]) + +if test "$with_secp256k1" != "node"; then + AX_SUBDIRS_CONFIGURE( + [$SECP256K1_PATH], + [[--enable-static], [--disable-shared], [--enable-experimental], [--enable-module-schnorrsig], [--enable-module-frost], [--enable-module-recovery]], + [[--disable-tests]], + [[--disable-benchmark], [--enable-examples], [--with-pic]], [[--disable-bench]]) - fi AC_OUTPUT @@ -358,26 +370,27 @@ AC_OUTPUT echo echo " ===============================================================================================================" echo " L15 config result:" -echo " build version = $VERSION" +echo " build version = $VERSION" +echo +echo " blockchain node = $NODE_PATH" +echo " secp256k1 = $with_secp256k1" echo -echo " debug enabled = $enable_debug" +echo " debug enabled = $enable_debug" echo -echo " build tools = $enable_build_tools" -echo " build services = $enable_build_services" -echo " build apis = $enable_build_apis" -echo " build inscribeit = $enable_build_inscribeit" -echo " plugin api = $enable_plugin_api" -echo " python module = $enable_python_module" -echo " wasm module = $enable_wasm_module" +echo " build FROST signer = $enable_build_frost_signer" +echo " build tools = $enable_build_tools" +echo " build services = $enable_build_services" +echo " build apis = $enable_build_apis" +echo " plugin api = $enable_plugin_api" echo -echo " target os = $host_os" -echo " build os = $build_os" +echo " target os = $host_os" +echo " build os = $build_os" echo -echo " CPPFLAGS = $CPPFLAGS $ZMQ_CPPFLAGS" -echo " CXX = $CXX" -echo " CXXFLAGS = $CXXFLAGS" -echo " LDFLAGS = $LDFLAGS $ZMQ_LDFLAGS" -echo " LIBS = $LIBS $ZMQ_LIBS" -echo " ARFLAGS = $ARFLAGS" +echo " CPPFLAGS = $CPPFLAGS $ZMQ_CPPFLAGS" +echo " CXX = $CXX" +echo " CXXFLAGS = $CXXFLAGS" +echo " LDFLAGS = $LDFLAGS $ZMQ_LDFLAGS" +echo " LIBS = $LIBS $ZMQ_LIBS" +echo " ARFLAGS = $ARFLAGS" echo " ===============================================================================================================" echo diff --git a/contrib/Makefile.am b/contrib/Makefile.am index cfe3988..271c46b 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -1 +1,2 @@ -SUBDIRS = secp256k1 \ No newline at end of file +SUBDIRS = +#secp256k1 \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am index 4560c55..cdcd663 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,15 +11,3 @@ endif if BUILD_TOOLS SUBDIRS += tools endif - -if BUILD_INSCRIBEIT -SUBDIRS += inscribeit -endif - -if BUILD_PYTHON_MODULE -SUBDIRS += python_binding -endif - -if BUILD_WASM_MODULE -SUBDIRS += wasm_binding -endif \ No newline at end of file diff --git a/src/api/Makefile.am b/src/api/Makefile.am index 45bdadd..f7af9e6 100644 --- a/src/api/Makefile.am +++ b/src/api/Makefile.am @@ -1,11 +1,11 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/contrib/secp256k1/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/p2p \ -I$(top_srcdir)/src/core \ @@ -16,5 +16,10 @@ noinst_LTLIBRARIES = libl15-api.la libl15_api_la_SOURCES = \ chain_api.cpp \ wallet_api.cpp \ - exechelper.cpp \ - signer_api.cpp + exechelper.cpp + +if BUILD_FROST + + libl15_api_la_SOURCES += signer_api.cpp + +endif \ No newline at end of file diff --git a/src/api/chain_api.hpp b/src/api/chain_api.hpp index eb61798..c76118c 100644 --- a/src/api/chain_api.hpp +++ b/src/api/chain_api.hpp @@ -20,9 +20,9 @@ class ChainApi { static std::regex sNewlineRegExp; std::vector m_default; - const char* m_cli_path; + std::string m_cli_path; public: - ChainApi(std::vector &&default_opts, const char *cli_path = "bitcoin-cli") + ChainApi(std::vector &&default_opts, const std::string& cli_path = "bitcoin-cli") : m_default(default_opts), m_cli_path(cli_path) { } ~ChainApi() = default; diff --git a/src/api/exechelper.cpp b/src/api/exechelper.cpp index 3f9b1d3..d974ac4 100644 --- a/src/api/exechelper.cpp +++ b/src/api/exechelper.cpp @@ -12,7 +12,7 @@ namespace pr = boost::process; namespace fs = boost::filesystem; -ExecHelper::ExecHelper(const char* command, bool autorun) : m_command(command), m_exitcode(std::numeric_limits::min()) +ExecHelper::ExecHelper(const std::string& command, bool autorun) : m_command(command), m_exitcode(std::numeric_limits::min()) { auto path = pr::search_path(command); if(path.empty()) { diff --git a/src/api/exechelper.hpp b/src/api/exechelper.hpp index a4841a8..db18abe 100644 --- a/src/api/exechelper.hpp +++ b/src/api/exechelper.hpp @@ -19,7 +19,7 @@ class ExecHelper { std::string m_out; int m_exitcode; public: - explicit ExecHelper(const char* command, bool autorun = true); + explicit ExecHelper(const std::string& command, bool autorun = true); ~ExecHelper() = default; std::vector& Arguments() { diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 2c64a3e..950c5fd 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -2,17 +2,17 @@ version.cpp: $(top_srcdir)/version.sh Makefile echo '#include "version.hpp"' >$@ (echo 'const char* const l15::Version::core_version = "'; $< $(top_srcdir); echo '";') | tr -d '\n' >>$@; echo >>$@ - (echo 'const char* const l15::Version::node_version = "'; $< $(top_srcdir)/node; echo '";')| tr -d '\n' >>$@; echo >>$@ - (echo 'const char* const l15::Version::secp256k1_version = "'; $< $(top_srcdir)/contrib/secp256k1; echo '";')| tr -d '\n' >>$@; echo >>$@ + (echo 'const char* const l15::Version::node_version = "'; $< $(top_srcdir)/$(NODE_PATH); echo '";')| tr -d '\n' >>$@; echo >>$@ + (echo 'const char* const l15::Version::secp256k1_version = "'; $< $(top_srcdir)/$(SECP256K1_PATH); echo '";')| tr -d '\n' >>$@; echo >>$@ AM_CPPFLAGS = \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/policy \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/contrib/secp256k1/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/policy \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/contrib/cex diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 5bcded1..edcd6a2 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -1,12 +1,12 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/primitives \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/contrib/secp256k1/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/primitives \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/contrib/cex diff --git a/src/inscribeit/Makefile.am b/src/inscribeit/Makefile.am deleted file mode 100644 index 51a5551..0000000 --- a/src/inscribeit/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ - -AM_CPPFLAGS = \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/primitives \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/node/src/policy \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/core \ - -I$(top_srcdir)/contrib/cex - - -noinst_LTLIBRARIES = libl15-inscribeit.la -libl15_inscribeit_la_SOURCES = \ - contract_builder.cpp \ - create_inscription.cpp \ - swap_inscription.cpp - -libl15_inscribeit_la_LDFLAGS = $(AM_LDFLAGS) -Wl,--gc-sections -libl15_inscribeit_la_CXXFLAGS = $(AM_CXXFLAGS) -ffunction-sections -fdata-sections diff --git a/src/inscribeit/contract_builder.cpp b/src/inscribeit/contract_builder.cpp deleted file mode 100644 index fdccc7d..0000000 --- a/src/inscribeit/contract_builder.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "contract_builder.hpp" -#include "interpreter.h" -#include "script_merkle_tree.hpp" -#include "channel_keys.hpp" - -namespace l15::inscribeit { - -const std::string ContractBuilder::name_contract_type = "contract_type"; -const std::string ContractBuilder::name_params = "params"; -const std::string ContractBuilder::name_version = "protocol_version"; -const std::string ContractBuilder::name_mining_fee_rate = "mining_fee_rate"; - -CAmount ContractBuilder::CalculateWholeFee() const { - auto txs = GetTransactions(); - return std::accumulate(txs.begin(), txs.end(), CAmount(0), [](CAmount sum, const auto &tx) { - return sum + l15::CalculateTxFee(tx.first, tx.second); - }); -} - -void ContractBuilder::VerifyTxSignature(const xonly_pubkey& pk, const signature& sig, const CMutableTransaction& tx, uint32_t nin, std::vector&& spent_outputs, const CScript& spend_script) -{ - if (sig.size() != 64 && sig.size() != 65) throw SignatureError("sig size"); - - uint256 sighash; - PrecomputedTransactionData txdata; - txdata.Init(tx, std::move(spent_outputs), true); - - ScriptExecutionData execdata; - execdata.m_annex_init = true; - execdata.m_annex_present = false; // Only support annex-less signing for now. - - if(!spend_script.empty()) { - execdata.m_codeseparator_pos_init = true; - execdata.m_codeseparator_pos = 0xFFFFFFFF; // Only support non-OP_CODESEPARATOR BIP342 signing for now. - execdata.m_tapleaf_hash_init = true; - execdata.m_tapleaf_hash = TapLeafHash(spend_script); - } - - uint8_t hashtype = SIGHASH_DEFAULT; - if (sig.size() == 65) { - hashtype = sig.back(); - if (hashtype == SIGHASH_DEFAULT) { - throw SignatureError("sighash type"); - } - } - - SigVersion sigversion = spend_script.empty() ? SigVersion::TAPROOT : SigVersion::TAPSCRIPT; - - if (!SignatureHashSchnorr(sighash, execdata, tx, nin, hashtype, sigversion, txdata, MissingDataBehavior::FAIL)) { - throw SignatureError("sighash"); - } - if (!pk.verify(core::ChannelKeys::GetStaticSecp256k1Context(), sig, sighash)) { - throw SignatureError("sig"); - } -} - -} // inscribeit diff --git a/src/inscribeit/contract_builder.hpp b/src/inscribeit/contract_builder.hpp deleted file mode 100644 index 4e0db31..0000000 --- a/src/inscribeit/contract_builder.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include - -#include "utils.hpp" -#include "contract_error.hpp" - -namespace l15::inscribeit { - -struct Transfer -{ - std::string m_txid; - uint32_t m_nout; - CAmount m_amount; - std::optional m_pubkey; - std::optional m_sig; -}; - -class ContractBuilder -{ -public: - static const std::string name_contract_type; - static const std::string name_params; - static const std::string name_version; - static const std::string name_mining_fee_rate; - -protected: - - std::optional m_mining_fee_rate; - - CAmount CalculateWholeFee() const; - virtual std::vector> GetTransactions() const = 0; - -public: - ContractBuilder() = default; - ContractBuilder(const ContractBuilder&) = default; - ContractBuilder(ContractBuilder&& ) noexcept = default; - - ContractBuilder& operator=(const ContractBuilder& ) = default; - ContractBuilder& operator=(ContractBuilder&& ) noexcept = default; - virtual std::string GetMinFundingAmount() const = 0; - - virtual uint32_t GetProtocolVersion() const = 0; - - std::string GetMiningFeeRate() const { return FormatAmount(m_mining_fee_rate.value()); } - void SetMiningFeeRate(const std::string& v) { m_mining_fee_rate = ParseAmount(v); } - - static void VerifyTxSignature(const xonly_pubkey& pk, const signature& sig, const CMutableTransaction& tx, uint32_t nin, std::vector&& spent_outputs, const CScript& spend_script); - - -}; - -} // inscribeit - diff --git a/src/inscribeit/contract_error.hpp b/src/inscribeit/contract_error.hpp deleted file mode 100644 index cb93cdc..0000000 --- a/src/inscribeit/contract_error.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#pragma once - -#include "common_error.hpp" - -namespace l15::inscribeit { - -class ContractError : public Error { -public: - explicit ContractError(std::string&& details) : Error(move(details)) {} - ~ContractError() override = default; - - const char* what() const noexcept override - { return "ContractError"; } -}; - -class ContractTermMissing : public ContractError { -public: - explicit ContractTermMissing(std::string&& details) : ContractError(move(details)) {} - ~ContractTermMissing() override = default; - - const char* what() const noexcept override - { return "ContractTermsMissing"; } -}; - -class ContractTermWrongValue : public ContractError { -public: - explicit ContractTermWrongValue(std::string&& details) : ContractError(move(details)) {} - ~ContractTermWrongValue() override = default; - - const char* what() const noexcept override - { return "ContractTermWrongValue"; } -}; - -class ContractValueMismatch : public ContractError { -public: - explicit ContractValueMismatch(std::string&& details) : ContractError(move(details)) {} - ~ContractValueMismatch() override = default; - - const char* what() const noexcept override - { return "ContractTermValueMismatch"; } -}; - -class ContractTermWrongFormat : public ContractError { -public: - explicit ContractTermWrongFormat(std::string&& details) : ContractError(move(details)) {} - ~ContractTermWrongFormat() override = default; - - const char* what() const noexcept override - { return "ContractTermWrongFormat"; } -}; - -class ContractStateError : public ContractError { -public: - explicit ContractStateError(std::string&& details) : ContractError(move(details)) {} - ~ContractStateError() override = default; - - const char* what() const noexcept override - { return "ContractStateError"; } -}; - -class ContractProtocolError : public ContractError { -public: - explicit ContractProtocolError(std::string&& details) : ContractError(move(details)) {} - ~ContractProtocolError() override = default; - - const char* what() const noexcept override - { return "ContractProtocolError"; } -}; - -} \ No newline at end of file diff --git a/src/inscribeit/create_inscription.cpp b/src/inscribeit/create_inscription.cpp deleted file mode 100644 index 58ed5af..0000000 --- a/src/inscribeit/create_inscription.cpp +++ /dev/null @@ -1,580 +0,0 @@ - -#include -#include - -#include "univalue.h" - -#include "serialize.h" -#include "interpreter.h" -#include "core_io.h" - -#include "streams.h" -#include "create_inscription.hpp" -#include "script_merkle_tree.hpp" -#include "channel_keys.hpp" - -namespace l15::inscribeit { - -namespace { - -const std::string val_create_inscription("CreateInscription"); - -const size_t chunk_size = 520; -const bytevector ORD_TAG {'o', 'r', 'd'}; -const opcodetype CONTENT_TAG {OP_0}; -const bytevector CONTENT_TYPE_TAG {'\1'}; -const bytevector COLLECTION_ID_TAG {'\2'}; - -CScript MakeInscriptionScript(const xonly_pubkey& pk, const std::string& content_type, const bytevector& data, const std::optional& inscription_id = {}) -{ - CScript script; - script << pk; - script << OP_CHECKSIG; - script << OP_0; - script << OP_IF; - script << ORD_TAG; - script << CONTENT_TYPE_TAG; - script << bytevector(content_type.begin(), content_type.end()); - - if (inscription_id) { - script << COLLECTION_ID_TAG; - script << bytevector(inscription_id->begin(), inscription_id->end()); - } - - script << CONTENT_TAG; - auto pos = data.begin(); - for ( ; pos + chunk_size < data.end(); pos += chunk_size) { - script << bytevector(pos, pos + chunk_size); - } - if (pos != data.end()) { - script << bytevector(pos, data.end()); - } - script << OP_ENDIF; - - return script; -} - -void CheckCollectionId(const std::string& collection_id) -{ - if (collection_id[64] != 'i') throw ContractTermWrongValue("collection id: " + collection_id); - try { - unhex(collection_id.substr(0, 64)); - std::stoul(collection_id.substr(65)); - } - catch (const std::exception& e) { - std::throw_with_nested(ContractTermWrongValue("collection id: " + collection_id)); - } -} - -} - -const uint32_t CreateInscriptionBuilder::m_protocol_version = 2; - -const std::string CreateInscriptionBuilder::name_ord_amount = "ord_amount"; -const std::string CreateInscriptionBuilder::name_utxo = "utxo"; -const std::string CreateInscriptionBuilder::name_utxo_txid = "txid"; -const std::string CreateInscriptionBuilder::name_utxo_nout = "nout"; -const std::string CreateInscriptionBuilder::name_utxo_amount = "amount"; -const std::string CreateInscriptionBuilder::name_utxo_pk = "pubkey"; -const std::string CreateInscriptionBuilder::name_utxo_sig = "sig"; -const std::string CreateInscriptionBuilder::name_collection = "collection"; -const std::string CreateInscriptionBuilder::name_collection_id = "collection_id"; -const std::string CreateInscriptionBuilder::name_content_type = "content_type"; -const std::string CreateInscriptionBuilder::name_content = "content"; -const std::string CreateInscriptionBuilder::name_inscribe_script_pk = "inscribe_script_pk"; -const std::string CreateInscriptionBuilder::name_inscribe_int_pk = "inscribe_int_pk"; -const std::string CreateInscriptionBuilder::name_inscribe_sig = "inscribe_sig"; -const std::string CreateInscriptionBuilder::name_destination_pk = "destination_pk"; - - -CreateInscriptionBuilder &CreateInscriptionBuilder::AddUTXO(const string &txid, uint32_t nout, const std::string& amount, const std::string& pk) -{ - m_utxo.emplace_back(std::string(txid), nout, ParseAmount(amount), unhex(pk)); - return *this; -} - -CreateInscriptionBuilder& CreateInscriptionBuilder::AddToCollection(const std::string& collection_id, - const string& utxo_txid, uint32_t utxo_nout, - const std::string& utxo_amount) -{ - CheckCollectionId(collection_id); - m_collection_id = collection_id; - m_collection_utxo = {utxo_txid, utxo_nout, ParseAmount(utxo_amount)}; - return *this; -} - -CreateInscriptionBuilder &CreateInscriptionBuilder::MiningFeeRate(const string &rate) -{ - SetMiningFeeRate(rate); - return *this; -} - -CreateInscriptionBuilder &CreateInscriptionBuilder::Data(const std::string& content_type, const string &hex_data) -{ - m_content_type = content_type; - m_content = unhex(hex_data); - return *this; -} - -CreateInscriptionBuilder &CreateInscriptionBuilder::DestinationPubKey(const string &pk) -{ - m_destination_pk = unhex(pk); - return *this; -} - -std::string CreateInscriptionBuilder::GetInscribeInternaltPubKey() const -{ - if (m_inscribe_int_pk) { - return hex(*m_inscribe_int_pk); - } - else - throw ContractStateError(std::string(name_inscribe_int_pk) + " undefined"); -} - -void CreateInscriptionBuilder::CheckBuildArgs() const -{ - if (!m_destination_pk) { - throw ContractTermMissing("destination pubkey"); - } - if (!m_content) { - throw ContractTermMissing("content"); - } - if (!m_content_type) { - throw ContractTermMissing("content-type"); - } - if (m_utxo.empty()) { - throw ContractTermMissing("UTXO"); - } - if (!m_mining_fee_rate) { - throw ContractTermMissing("mining fee rate"); - } - CheckAmount(); -} - -void CreateInscriptionBuilder::CheckAmount() const -{ - CAmount utxo_amount = 0; - for (const auto& utxo: m_utxo) { - utxo_amount += utxo.m_amount; - } - if (utxo_amount < m_ord_amount + CalculateWholeFee()) { - throw ContractTermWrongValue("UTXO amount is not enough"); - } - if (m_collection_utxo && m_collection_utxo->m_amount <= Dust(*m_mining_fee_rate)) { - throw ContractTermWrongValue("collection UTXO amount is not enough"); - } -} - - -void CreateInscriptionBuilder::SignCommit(uint32_t n, const std::string& sk, const std::string& inscribe_script_pk) -{ - if (n >= m_utxo.size()) throw ContractTermMissing(name_utxo + '[' + std::to_string(n) + ']'); - CheckBuildArgs(); - - auto utxo_it = m_utxo.begin(); - std::advance(utxo_it, n); - core::ChannelKeys utxo_key(unhex(sk)); - if (utxo_key.GetLocalPubKey() != utxo_it->m_pubkey) throw ContractValueMismatch(name_utxo + '[' + std::to_string(n) + ']' + name_utxo_pk); - - if (!m_inscribe_int_pk) { - core::ChannelKeys inscribe_internal_key = core::ChannelKeys(); - m_inscribe_int_sk = inscribe_internal_key.GetLocalPrivKey(); - m_inscribe_int_pk = inscribe_internal_key.GetLocalPubKey(); - } - - if (m_inscribe_script_pk) { - if (*m_inscribe_script_pk != unhex(inscribe_script_pk)) throw ContractValueMismatch(std::string(name_inscribe_script_pk)); - } - else { - m_inscribe_script_pk = unhex(inscribe_script_pk); - } - - CAmount utxo_amount = 0; - std::vector spending_outs; - spending_outs.reserve(m_utxo.size()); - for (const auto& utxo: m_utxo) { - utxo_amount += utxo.m_amount; - spending_outs.emplace_back(utxo.m_amount, CScript() << 1 << *utxo.m_pubkey); - } - - CMutableTransaction funding_tx = CreateCommitTxTemplate(); - funding_tx.vout.front().nValue = CalculateOutputAmount(utxo_amount, *m_mining_fee_rate, funding_tx); - - utxo_it->m_sig = utxo_key.SignTaprootTx(funding_tx, n, move(spending_outs), {}); -} - -void CreateInscriptionBuilder::SignCollection(const std::string& sk) -{ - CheckBuildArgs(); - - if (!m_inscribe_script_pk) throw ContractStateError(std::string(name_inscribe_script_pk) + " undefined"); - if (!m_inscribe_int_sk) throw ContractStateError(std::string("internal inscription key undefined: has commit tx been signed?")); - - core::ChannelKeys collection_key(unhex(sk)); - m_collection_utxo->m_pubkey = collection_key.GetLocalPubKey(); - - if (!m_inscribe_taproot_sk) { - CScript genesis_script = MakeInscriptionScript(*m_inscribe_script_pk, *m_content_type, *m_content, m_collection_id); - ScriptMerkleTree genesis_tap_tree(TreeBalanceType::WEIGHTED, {genesis_script}); - uint256 root = genesis_tap_tree.CalculateRoot(); - - core::ChannelKeys inscribe_internal_key(*m_inscribe_int_sk); - auto taproot = inscribe_internal_key.NewKeyAddTapTweak(root); - m_inscribe_taproot_sk = taproot.first.GetLocalPrivKey(); - } - - const CMutableTransaction& commit_tx = CommitTx(); - - CMutableTransaction genesis_tx = CreateGenesisTxTemplate(); - genesis_tx.vin[0].prevout.hash = commit_tx.GetHash(); - - genesis_tx.vout.front().nValue = CalculateOutputAmount(commit_tx.vout.front().nValue, *m_mining_fee_rate, genesis_tx); - - std::vector spending_outs = {commit_tx.vout.front(), {m_collection_utxo->m_amount, CScript() << 1 << *m_collection_utxo->m_pubkey}}; - - m_collection_utxo->m_sig = collection_key.SignTaprootTx(genesis_tx, 1, move(spending_outs), {}); -} - -void CreateInscriptionBuilder::SignInscription(const std::string& insribe_script_sk) -{ - core::ChannelKeys script_keypair(unhex(insribe_script_sk)); - if (!m_inscribe_script_pk) throw ContractStateError(std::string(name_inscribe_script_pk) + " undefined"); - if (*m_inscribe_script_pk != script_keypair.GetLocalPubKey()) throw ContractValueMismatch(std::string(name_inscribe_script_pk)); - if (!m_inscribe_int_sk) throw ContractStateError(std::string("internal inscription key undefined: has commit tx been signed?")); - if (m_collection_utxo && !m_collection_utxo->m_pubkey) throw ContractStateError("Need signed collection input before inscription"); - - CScript genesis_script = MakeInscriptionScript(*m_inscribe_script_pk, *m_content_type, *m_content, m_collection_id); - if (!m_inscribe_taproot_sk) { - ScriptMerkleTree genesis_tap_tree(TreeBalanceType::WEIGHTED, {genesis_script}); - uint256 root = genesis_tap_tree.CalculateRoot(); - - core::ChannelKeys inscribe_internal_key(*m_inscribe_int_sk); - auto taproot = inscribe_internal_key.NewKeyAddTapTweak(root); - m_inscribe_taproot_sk = taproot.first.GetLocalPrivKey(); - } - - const CMutableTransaction& commit_tx = CommitTx(); - CMutableTransaction genesis_tx = CreateGenesisTxTemplate(); - genesis_tx.vin[0].prevout.hash = commit_tx.GetHash(); - - genesis_tx.vout.front().nValue = CalculateOutputAmount(commit_tx.vout.front().nValue, *m_mining_fee_rate, genesis_tx); - - std::vector spending_outs = {commit_tx.vout.front()}; - if (m_collection_utxo) { - spending_outs.emplace_back(m_collection_utxo->m_amount, CScript() << 1 << *m_collection_utxo->m_pubkey); - } - - m_inscribe_script_sig = script_keypair.SignTaprootTx(genesis_tx, 0, move(spending_outs), genesis_script); -} - -std::vector CreateInscriptionBuilder::RawTransactions() const -{ - if (!mCommitTx || !mGenesisTx) { - throw ContractStateError("Transaction data unavailable"); - } - - std::string funding_tx_hex = EncodeHexTx(CTransaction(*mCommitTx)); - std::string genesis_tx_hex = EncodeHexTx(CTransaction(*mGenesisTx)); - return {move(funding_tx_hex), move(genesis_tx_hex)}; -} - -std::string CreateInscriptionBuilder::Serialize() const -{ - UniValue contract(UniValue::VOBJ); - contract.pushKV(name_version, (int)m_protocol_version); - contract.pushKV(name_ord_amount, m_ord_amount); - contract.pushKV(name_mining_fee_rate, *m_mining_fee_rate); - - UniValue utxo_arr(UniValue::VARR); - for (const auto& utxo: m_utxo) { - UniValue utxo_val(UniValue::VOBJ); - utxo_val.pushKV(name_utxo_txid, utxo.m_txid); - utxo_val.pushKV(name_utxo_nout, utxo.m_nout); - utxo_val.pushKV(name_utxo_amount, utxo.m_amount); - utxo_val.pushKV(name_utxo_sig, hex(*utxo.m_sig)); - - utxo_arr.push_back(move(utxo_val)); - } - contract.pushKV(name_utxo, utxo_arr); - - if (m_collection_utxo) { - UniValue collection_val(UniValue::VOBJ); - collection_val.pushKV(name_utxo_txid, m_collection_utxo->m_txid); - collection_val.pushKV(name_utxo_nout, m_collection_utxo->m_nout); - collection_val.pushKV(name_utxo_amount, m_collection_utxo->m_amount); - collection_val.pushKV(name_utxo_pk, hex(*m_collection_utxo->m_pubkey)); - collection_val.pushKV(name_utxo_sig, hex(*m_collection_utxo->m_sig)); - collection_val.pushKV(name_collection_id, *m_collection_id); - contract.pushKV(name_collection, move(collection_val)); - } - - contract.pushKV(name_content_type, m_content_type.value()); - contract.pushKV(name_content, hex(m_content.value())); - - contract.pushKV(name_inscribe_script_pk, hex(m_inscribe_script_pk.value())); - contract.pushKV(name_inscribe_int_pk, GetInscribeInternaltPubKey()); - contract.pushKV(name_inscribe_sig, hex(m_inscribe_script_sig.value())); - - contract.pushKV(name_destination_pk, hex(m_destination_pk.value())); - - UniValue dataRoot(UniValue::VOBJ); - dataRoot.pushKV(name_contract_type, val_create_inscription); - dataRoot.pushKV(name_params, move(contract)); - - return dataRoot.write(); -} - -void CreateInscriptionBuilder::Deserialize(const string &data) -{ - UniValue root; - root.read(data); - - if (root[name_contract_type].get_str() != val_create_inscription) { - throw ContractProtocolError("CreateInscription contract does not match " + root[name_contract_type].getValStr()); - } - - const UniValue& contract = root[name_params]; - - if (contract[name_version].getInt() != m_protocol_version) { - throw ContractProtocolError("Wrong CreateInscription contract version: " + contract[name_version].getValStr()); - } - - { const auto &val = contract[name_ord_amount]; - if (val.isNull()) throw ContractTermMissing(std::string(name_ord_amount)); - if (!val.isNum() || val.getInt() != m_ord_amount) - throw ContractTermWrongValue(std::string(name_ord_amount) + ": " + contract[name_ord_amount].getValStr() + ", awaited: " + std::to_string(m_ord_amount)); - } - - { const auto &val = contract[name_utxo]; - - if (val.isNull()) throw ContractTermMissing(std::string(name_utxo)); - if (!val.isArray()) throw ContractTermWrongFormat(std::string(name_utxo)); - if (val.empty()) throw ContractTermMissing(std::string(name_utxo)); - - for (size_t n = 0; n < val.size(); ++n) { - const UniValue &utxo = val[n]; - - if (!utxo.exists(name_utxo_txid)) - throw ContractTermMissing(std::string(name_utxo) + '[' + std::to_string(n) + "]." + name_utxo_txid); - if (!utxo.exists(name_utxo_nout)) - throw ContractTermMissing(std::string(name_utxo) + '[' + std::to_string(n) + "]." + name_utxo_nout); - if (!utxo.exists(name_utxo_amount)) - throw ContractTermMissing(std::string(name_utxo) + '[' + std::to_string(n) + "]." + name_utxo_amount); - if (!utxo.exists(name_utxo_sig)) - throw ContractTermMissing(std::string(name_utxo) + '[' + std::to_string(n) + "]." + name_utxo_sig); - - std::string txid = utxo[name_utxo_txid].get_str(); - uint32_t nout = utxo[name_utxo_nout].getInt(); - CAmount amount = utxo[name_utxo_amount].getInt(); - signature sig = unhex(utxo[name_utxo_sig].get_str()); - - m_utxo.emplace_back(move(txid), nout, amount); - m_utxo.back().m_sig = move(sig); - } - } - { const auto &val = contract[name_collection]; - if (!val.isNull()) { - if (!val.isObject()) throw ContractTermWrongFormat(std::string(name_collection)); - - if (!val.exists(name_utxo_txid)) - throw ContractTermMissing(std::string(name_collection) + "." + name_utxo_txid); - if (!val.exists(name_utxo_nout)) - throw ContractTermMissing(std::string(name_collection) + "." + name_utxo_nout); - if (!val.exists(name_utxo_amount)) - throw ContractTermMissing(std::string(name_collection) + "." + name_utxo_amount); - if (!val.exists(name_utxo_pk)) - throw ContractTermMissing(std::string(name_collection) + "." + name_utxo_pk); - if (!val.exists(name_utxo_sig)) - throw ContractTermMissing(std::string(name_collection) + "." + name_utxo_sig); - if (!val.exists(name_collection_id)) - throw ContractTermMissing(std::string(name_collection) + "." + name_collection_id); - - m_collection_id = val[name_collection_id].get_str(); - - std::string txid = val[name_utxo_txid].get_str(); - uint32_t nout = val[name_utxo_nout].getInt(); - CAmount amount = val[name_utxo_amount].getInt(); - xonly_pubkey pk = unhex(val[name_utxo_pk].get_str()); - signature sig = unhex(val[name_utxo_sig].get_str()); - - m_collection_utxo = {move(txid), nout, amount, move(pk), move(sig)}; - } - } - { const auto &val = contract[name_mining_fee_rate]; - if (val.isNull()) throw ContractTermMissing(std::string(name_mining_fee_rate)); - m_mining_fee_rate = val.getInt(); - } - { const auto &val = contract[name_content_type]; - if (val.isNull()) throw ContractTermMissing(std::string(name_content_type)); - m_content_type = val.get_str(); - } - { const auto &val = contract[name_content]; - if (val.isNull()) throw ContractTermMissing(std::string(name_content)); - m_content = unhex(val.get_str()); - } - { const auto &val = contract[name_inscribe_script_pk]; - if (val.isNull()) throw ContractTermMissing(std::string(name_inscribe_script_pk)); - m_inscribe_script_pk = unhex(val.get_str()); - } - { const auto &val = contract[name_inscribe_sig]; - if (val.isNull()) throw ContractTermMissing(std::string(name_inscribe_sig)); - m_inscribe_script_sig = unhex(val.get_str()); - } - { const auto &val = contract[name_inscribe_int_pk]; - if (val.isNull()) throw ContractTermMissing(std::string(name_inscribe_int_pk)); - m_inscribe_int_pk = unhex(val.get_str()); - } - { const auto &val = contract[name_destination_pk]; - if (val.isNull()) throw ContractTermMissing(std::string(name_destination_pk)); - m_destination_pk = unhex(val.get_str()); - } - CheckAmount(); - - RestoreTransactions(); -} - -const CMutableTransaction& CreateInscriptionBuilder::CommitTx() const -{ - if (!mCommitTx) { - if (m_utxo.empty()) throw ContractTermMissing(std::string(name_utxo)); - uint32_t n = 0; - CAmount utxo_amount = 0; - for (const auto& utxo: m_utxo) { - if (!utxo.m_sig) throw ContractTermMissing(std::string(name_utxo) + '[' + std::to_string(n) + "]." + name_utxo_sig); - utxo_amount += utxo.m_amount; - ++n; - } - - CMutableTransaction tx = CreateCommitTxTemplate(); - tx.vout.front().nValue = CalculateOutputAmount(utxo_amount, *m_mining_fee_rate, tx); - mCommitTx = move(tx); - } - return *mCommitTx; -} - - -void CreateInscriptionBuilder::RestoreTransactions() -{ - if (!m_inscribe_script_pk) throw ContractTermMissing(std::string(name_inscribe_script_pk)); - if (!m_inscribe_int_pk) throw ContractTermMissing(std::string(name_inscribe_int_pk)); - if (!m_inscribe_script_sig) throw ContractTermMissing(std::string(name_inscribe_sig)); - - if (!m_collection_id && m_collection_utxo) throw ContractTermMissing(std::string(name_collection_id)); - if (!m_collection_utxo && m_collection_id) throw ContractTermMissing(std::string(name_collection)); - if (m_collection_utxo) { - if (!m_collection_utxo->m_pubkey) throw ContractTermMissing(std::string(name_collection) + '.' + name_utxo_pk); - if (!m_collection_utxo->m_sig) throw ContractTermMissing(std::string(name_collection) + '.' + name_utxo_sig); - } - - const CMutableTransaction& commit_tx = CommitTx(); - CMutableTransaction genesis_tx = CreateGenesisTxTemplate(); - genesis_tx.vin[0].prevout.hash = commit_tx.GetHash(); - genesis_tx.vin[0].scriptWitness.stack[0] = *m_inscribe_script_sig; - genesis_tx.vout[0].nValue = CalculateOutputAmount(commit_tx.vout.front().nValue, *m_mining_fee_rate, genesis_tx); - - mGenesisTx.emplace(move(genesis_tx)); -} - -CMutableTransaction CreateInscriptionBuilder::CreateCommitTxTemplate() const { - - CMutableTransaction result; - - if (!m_utxo.empty()) { - result.vin.reserve(m_utxo.size()); - for (const auto &utxo: m_utxo) { - result.vin.emplace_back(uint256S(utxo.m_txid), utxo.m_nout); - result.vin.back().scriptWitness.stack.emplace_back(utxo.m_sig.value_or(signature())); - } - } - else { - result.vin.emplace_back(uint256(), 0); - result.vin.back().scriptWitness.stack.emplace_back(64); - } - - CScript pubkey_script; - pubkey_script << 1; - if (m_inscribe_taproot_sk) { - core::ChannelKeys taproot_keypair(*m_inscribe_taproot_sk); - pubkey_script << taproot_keypair.GetLocalPubKey(); - } - else if (m_inscribe_int_pk && m_inscribe_script_pk) { - CScript genesis_script = MakeInscriptionScript(*m_inscribe_script_pk, *m_content_type, *m_content, m_collection_id); - ScriptMerkleTree genesis_tap_tree(TreeBalanceType::WEIGHTED, {genesis_script}); - uint256 root = genesis_tap_tree.CalculateRoot(); - auto taproot = core::ChannelKeys::AddTapTweak(*m_inscribe_int_pk, root); - pubkey_script << get<0>(taproot); - } - else { - pubkey_script << xonly_pubkey(); - } - - result.vout.emplace_back(0, pubkey_script); - - return result; -} - -CMutableTransaction CreateInscriptionBuilder::CreateGenesisTxTemplate() const { - if (!m_content_type) throw ContractStateError(std::string(name_content_type) + " undefined"); - if (!m_content) throw ContractStateError(std::string(name_content) + " undefined"); - - auto emptyKey = xonly_pubkey(); - - CScript genesis_script = MakeInscriptionScript(m_inscribe_script_pk ? *m_inscribe_script_pk : emptyKey, *m_content_type, *m_content, m_collection_id); - ScriptMerkleTree genesis_tap_tree(TreeBalanceType::WEIGHTED, {genesis_script}); - uint256 root = genesis_tap_tree.CalculateRoot(); - - uint8_t taproot_parity = 0; - if (m_inscribe_int_pk) { - auto taproot = core::ChannelKeys::AddTapTweak(*m_inscribe_int_pk, root); - taproot_parity = taproot.second; - } - - std::vector genesis_scriptpath = genesis_tap_tree.CalculateScriptPath(genesis_script); - bytevector control_block = {static_cast(0xc0 | taproot_parity)}; - control_block.reserve(1 + emptyKey.size() + genesis_scriptpath.size() * uint256::size()); - if (m_inscribe_int_pk) { - control_block.insert(control_block.end(), m_inscribe_int_pk->begin(), m_inscribe_int_pk->end()); - } - else { - control_block.insert(control_block.end(), emptyKey.begin(), emptyKey.end()); - } - - for(uint256 &branch_hash : genesis_scriptpath) - control_block.insert(control_block.end(), branch_hash.begin(), branch_hash.end()); - - CMutableTransaction result; - - result.vin = {{uint256(0), 0}}; - result.vin.front().scriptWitness.stack.emplace_back(m_inscribe_script_sig.value_or(signature())); - result.vin.front().scriptWitness.stack.emplace_back(genesis_script.begin(), genesis_script.end()); - result.vin.front().scriptWitness.stack.emplace_back(control_block); - - result.vout = {CTxOut(0, CScript() << 1 << m_destination_pk.value_or(emptyKey))}; - - if (m_collection_utxo) { - result.vin.emplace_back(uint256S(m_collection_utxo->m_txid), m_collection_utxo->m_nout); - result.vin.back().scriptWitness.stack.emplace_back(m_collection_utxo->m_sig.value_or(signature())); - result.vout.emplace_back(m_collection_utxo->m_amount, CScript() << 1 << m_collection_utxo->m_pubkey.value_or(xonly_pubkey())); - } - - return result; -} - -std::vector> CreateInscriptionBuilder::GetTransactions() const { - return { - { *m_mining_fee_rate, CreateCommitTxTemplate() }, - { *m_mining_fee_rate, CreateGenesisTxTemplate()} - }; -} - -std::string CreateInscriptionBuilder::GetMinFundingAmount() const { - if(!m_content_type) { - throw l15::TransactionError("content type is empty"); - } - if(!m_content) { - throw l15::TransactionError("content is empty"); - } - return FormatAmount(m_ord_amount + CalculateWholeFee()); -} - -} diff --git a/src/inscribeit/create_inscription.hpp b/src/inscribeit/create_inscription.hpp deleted file mode 100644 index 343ef00..0000000 --- a/src/inscribeit/create_inscription.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "univalue.h" - -#include "common.hpp" -#include "contract_builder.hpp" - -namespace l15::inscribeit { - -class CreateInscriptionBuilder; - -class CreateInscriptionBuilder: public ContractBuilder -{ - static const uint32_t m_protocol_version; - CAmount m_ord_amount; - - std::list m_utxo; - - std::optional m_collection_id; - std::optional m_collection_utxo; - - std::optional m_content_type; - std::optional m_content; - - std::optional m_inscribe_script_pk; - std::optional m_inscribe_script_sig; - - std::optional m_inscribe_taproot_sk; // needed in case of a fallback scenario to return funds - std::optional m_inscribe_int_sk; //taproot - std::optional m_inscribe_int_pk; //taproot - - std::optional m_destination_pk; - - mutable std::optional mCommitTx; - mutable std::optional mGenesisTx; - -private: - void CheckBuildArgs() const; - void CheckAmount() const; - - void RestoreTransactions(); - -protected: - std::vector> GetTransactions() const override; - - CMutableTransaction CreateCommitTxTemplate() const; - CMutableTransaction CreateGenesisTxTemplate() const; - - const CMutableTransaction& CommitTx() const; - -public: - - static const std::string name_ord_amount; - static const std::string name_utxo; - static const std::string name_utxo_txid; - static const std::string name_utxo_nout; - static const std::string name_utxo_amount; - static const std::string name_utxo_pk; - static const std::string name_content_type; - static const std::string name_content; - static const std::string name_utxo_sig; - static const std::string name_collection; - static const std::string name_collection_id; - static const std::string name_inscribe_script_pk; - static const std::string name_inscribe_int_pk; - static const std::string name_inscribe_sig; - static const std::string name_destination_pk; - - CreateInscriptionBuilder() : m_ord_amount(0) {} - CreateInscriptionBuilder(const CreateInscriptionBuilder&) = default; - CreateInscriptionBuilder(CreateInscriptionBuilder&&) noexcept = default; - - explicit CreateInscriptionBuilder(const std::string& amount) : m_ord_amount(ParseAmount(amount)) {} - - CreateInscriptionBuilder& operator=(const CreateInscriptionBuilder&) = default; - CreateInscriptionBuilder& operator=(CreateInscriptionBuilder&&) noexcept = default; - - uint32_t GetProtocolVersion() const override { return m_protocol_version; } - - std::string GetContentType() const { return m_content_type.value(); } - void SetContentType(std::string v) { m_content_type = v; } - - std::string GetContent() const { return l15::hex(m_content.value()); } - void SetContent(std::string v) { m_content = unhex(v); } - - std::string GetDestinationPubKey() const { return l15::hex(m_destination_pk.value()); } - void SetDestinationPubKey(std::string v) { m_destination_pk = unhex(v); } - - std::string GetIntermediateSecKey() const { return l15::hex(m_inscribe_taproot_sk.value()); } - - CreateInscriptionBuilder& MiningFeeRate(const std::string& rate); - CreateInscriptionBuilder& AddUTXO(const string &txid, uint32_t nout, const std::string& amount, const std::string& pk); - CreateInscriptionBuilder& Data(const std::string& content_type, const std::string& hex_data); - CreateInscriptionBuilder& DestinationPubKey(const std::string& pk); - CreateInscriptionBuilder& AddToCollection(const std::string& collection_id, const string& utxo_txid, uint32_t utxo_nout, const std::string& utxo_amount); - - std::string getIntermediateTaprootSK() const - { return hex(m_inscribe_taproot_sk.value()); } - - std::string GetInscribeScriptPubKey() const - { return hex(m_inscribe_script_pk.value()); } - - std::string GetInscribeScriptSig() const - { return hex(m_inscribe_script_sig.value()); } - - std::string GetInscribeInternaltPubKey() const; - - void SignCommit(uint32_t n, const std::string& sk, const std::string& inscribe_script_pk); - void SignCollection(const std::string& sk); - void SignInscription(const std::string& insribe_script_sk); - - std::string GetMinFundingAmount() const override; - - std::vector RawTransactions() const; - - std::string Serialize() const; - void Deserialize(const std::string& data); - -}; - -} // inscribeit - diff --git a/src/inscribeit/swap_inscription.cpp b/src/inscribeit/swap_inscription.cpp deleted file mode 100644 index f36a13d..0000000 --- a/src/inscribeit/swap_inscription.cpp +++ /dev/null @@ -1,890 +0,0 @@ -#include -//#include - -#include "swap_inscription.hpp" - -#include "univalue.h" - -#include "core_io.h" -#include "policy.h" - -#include "channel_keys.hpp" - -namespace l15::inscribeit { - -namespace { - -const std::string val_swap_inscription("SwapInscription"); - -const uint32_t COMMIT_TIMEOUT = 12; - - -CScript MakeFundsSwapScript(const xonly_pubkey& pk_B, const xonly_pubkey& pk_M) -{ - CScript script; - script << pk_B << OP_CHECKSIG; - script << pk_M << OP_CHECKSIGADD; - script << 2 << OP_NUMEQUAL; - return script; -} - -CScript MakeRelTimeLockScript(uint32_t blocks_to_lock, const xonly_pubkey& pk) -{ - CScript script; - script << GetCsvInBlocks(blocks_to_lock) << OP_CHECKSEQUENCEVERIFY << OP_DROP; - script << pk << OP_CHECKSIG; - return script; -} - -} - -const uint32_t SwapInscriptionBuilder::m_protocol_version = 2; - -const std::string SwapInscriptionBuilder::name_ord_price = "ord_price"; -const std::string SwapInscriptionBuilder::name_market_fee = "market_fee"; - -const std::string SwapInscriptionBuilder::name_swap_script_pk_A = "swap_script_pk_A"; -const std::string SwapInscriptionBuilder::name_swap_script_pk_B = "swap_script_pk_B"; -const std::string SwapInscriptionBuilder::name_swap_script_pk_M = "swap_script_pk_M"; - -const std::string SwapInscriptionBuilder::name_ord_txid = "ord_txid"; -const std::string SwapInscriptionBuilder::name_ord_nout = "ord_nout"; -const std::string SwapInscriptionBuilder::name_ord_amount = "ord_amount"; -const std::string SwapInscriptionBuilder::name_ord_pk = "ord_pk"; - - -const std::string SwapInscriptionBuilder::name_funds = "funds"; -const std::string SwapInscriptionBuilder::name_funds_unspendable_key_factor = "funds_unspendable_key_factor"; -const std::string SwapInscriptionBuilder::name_funds_txid = "funds_txid"; -const std::string SwapInscriptionBuilder::name_funds_nout = "funds_nout"; -const std::string SwapInscriptionBuilder::name_funds_amount = "funds_amount"; - -const std::string SwapInscriptionBuilder::name_funds_commit_sig = "funds_commit_sig"; - -const std::string SwapInscriptionBuilder::name_ord_swap_sig_A = "ord_swap_sig_A"; -const std::string SwapInscriptionBuilder::name_funds_swap_sig_B = "funds_swap_sig_B"; -const std::string SwapInscriptionBuilder::name_funds_swap_sig_M = "funds_swap_sig_M"; - -const std::string SwapInscriptionBuilder::name_ordpayoff_unspendable_key_factor = "ordpayoff_unspendable_key_factor"; -const std::string SwapInscriptionBuilder::name_ordpayoff_sig = "ordpayoff_sig"; - -SwapInscriptionBuilder::SwapInscriptionBuilder(const string &ord_price, const string &market_fee) - : ContractBuilder(), m_ord_price(ParseAmount(ord_price)), m_market_fee(ParseAmount(market_fee)) {}; - - - -std::tuple SwapInscriptionBuilder::FundsCommitTapRoot() const -{ - ScriptMerkleTree tap_tree(TreeBalanceType::WEIGHTED, - { MakeFundsSwapScript(m_swap_script_pk_B.value(), m_swap_script_pk_M.value()), - MakeRelTimeLockScript(COMMIT_TIMEOUT, m_swap_script_pk_B.value())}); - - return std::tuple_cat(core::ChannelKeys::AddTapTweak(core::ChannelKeys::CreateUnspendablePubKey(m_funds_unspendable_key_factor.value()), - tap_tree.CalculateRoot()), std::make_tuple(tap_tree)); -} - -std::tuple SwapInscriptionBuilder::FundsCommitTemplateTapRoot() const -{ - xonly_pubkey pubKey; - ScriptMerkleTree tap_tree(TreeBalanceType::WEIGHTED, - { MakeFundsSwapScript(pubKey, pubKey), - MakeRelTimeLockScript(COMMIT_TIMEOUT, pubKey)}); - - return std::tuple_cat(std::pair(pubKey, 0), std::make_tuple(tap_tree)); -} - -CMutableTransaction SwapInscriptionBuilder::GetSwapTxTemplate() const { - - if (!mSwapTpl) { - CMutableTransaction swapTpl; - swapTpl.vin.reserve(2); - swapTpl.vout.reserve(3); - - swapTpl.vout.emplace_back(0, CScript() << 1 << *m_swap_script_pk_M); - swapTpl.vout.emplace_back(m_ord_price, CScript() << 1 << xonly_pubkey()); - swapTpl.vout.emplace_back(*m_market_fee, CScript() << 1 << *m_swap_script_pk_M); - - swapTpl.vin.emplace_back(COutPoint(uint256(), 0)); - swapTpl.vin.back().scriptWitness.stack.emplace_back(65); - - auto taproot = FundsCommitTemplateTapRoot(); - - xonly_pubkey funds_unspendable_key; - - CScript &funds_swap_script = get<2>(taproot).GetScripts()[0]; - - auto funds_scriptpath = get<2>(taproot).CalculateScriptPath(funds_swap_script); - bytevector funds_control_block = {0}; - funds_control_block.reserve(1 + funds_unspendable_key.size() + funds_scriptpath.size() * uint256::size()); - funds_control_block.insert(funds_control_block.end(), funds_unspendable_key.begin(), funds_unspendable_key.end()); - for (uint256 &branch_hash: funds_scriptpath) - funds_control_block.insert(funds_control_block.end(), branch_hash.begin(), branch_hash.end()); - - swapTpl.vin.emplace_back(uint256(0), 0); - swapTpl.vin.back().scriptWitness.stack.emplace_back(64); - swapTpl.vin.back().scriptWitness.stack.emplace_back(64); - - swapTpl.vin.back().scriptWitness.stack.emplace_back(funds_swap_script.begin(), funds_swap_script.end()); - swapTpl.vin.back().scriptWitness.stack.emplace_back(move(funds_control_block)); - - mSwapTpl = move(swapTpl); - } - return *mSwapTpl; -} - -CMutableTransaction SwapInscriptionBuilder::MakeSwapTx(bool with_funds_in) const -{ - CMutableTransaction swap_tx = GetSwapTxTemplate(); - - swap_tx.vin[0].prevout = COutPoint(uint256S(*m_ord_txid), *m_ord_nout); - if (m_ord_swap_sig_A) { - swap_tx.vin[0].scriptWitness.stack[0] = *m_ord_swap_sig_A; - } - - swap_tx.vout[0].nValue = *m_ord_amount; - swap_tx.vout[1].scriptPubKey = CScript() << 1 << *m_swap_script_pk_A; - - if (with_funds_in) { - auto funds_commit_taproot = FundsCommitTapRoot(); - - xonly_pubkey funds_unspendable_key = core::ChannelKeys::CreateUnspendablePubKey(*m_funds_unspendable_key_factor); - - CScript& funds_swap_script = get<2>(funds_commit_taproot).GetScripts()[0]; - - auto funds_scriptpath = get<2>(funds_commit_taproot).CalculateScriptPath(funds_swap_script); - bytevector funds_control_block = {static_cast(0xc0 | get<1>(funds_commit_taproot))}; - funds_control_block.reserve(1 + funds_unspendable_key.size() + funds_scriptpath.size() * uint256::size()); - funds_control_block.insert(funds_control_block.end(), funds_unspendable_key.begin(), funds_unspendable_key.end()); - for(uint256 &branch_hash : funds_scriptpath) - funds_control_block.insert(funds_control_block.end(), branch_hash.begin(), branch_hash.end()); - - swap_tx.vin[1].prevout.hash = GetFundsCommitTx().GetHash(); - swap_tx.vin[1].prevout.n = 0; - - if (m_funds_swap_sig_M) { - swap_tx.vin[1].scriptWitness.stack[0] = *m_funds_swap_sig_M; - } - if (m_funds_swap_sig_B) { - swap_tx.vin[1].scriptWitness.stack[1] = *m_funds_swap_sig_B; - } - swap_tx.vin[1].scriptWitness.stack[2] = std::vector(funds_swap_script.begin(), funds_swap_script.end()); - swap_tx.vin[1].scriptWitness.stack[3] = std::move(funds_control_block); - } - else { - swap_tx.vin.pop_back(); - } - return swap_tx; -} - -void SwapInscriptionBuilder::SignOrdSwap(const std::string& sk) -{ - core::ChannelKeys keypair(unhex(sk)); - - m_ord_pk = keypair.GetLocalPubKey(); - - auto utxo_pubkeyscript = CScript() << 1 << (keypair.GetLocalPubKey()); - - CMutableTransaction swap_tx(MakeSwapTx(false)); - - m_ord_swap_sig_A = keypair.SignTaprootTx(swap_tx, 0, {CTxOut(*m_ord_amount, utxo_pubkeyscript)}, {}, SIGHASH_ALL|SIGHASH_ANYONECANPAY); -} - -CMutableTransaction& SwapInscriptionBuilder::GetFundsCommitTxTemplate() const -{ - if (!mFundsCommitTpl) { - auto commit_pubkeyscript = CScript() << 1 << get<0>(FundsCommitTemplateTapRoot()); - auto change_pubkeyscript = CScript() << 1 << xonly_pubkey(); - - CMutableTransaction commit_tx; - - commit_tx.vout = {CTxOut(0, commit_pubkeyscript), CTxOut(0, change_pubkeyscript)}; - - mFundsCommitTpl = move(commit_tx); - } - mFundsCommitTpl->vin.reserve(m_funds.size()); - - if (m_funds.empty()) { - mFundsCommitTpl->vin.emplace_back(uint256(), 0); - mFundsCommitTpl->vin.back().scriptWitness.stack.emplace_back(64); - } - else { - uint32_t n = 0; - for (const auto &utxo: m_funds) { - if (mFundsCommitTpl->vin.size() > n) { - mFundsCommitTpl->vin[n].prevout = COutPoint(uint256S(utxo.m_txid), utxo.m_nout); - if (utxo.m_sig) - mFundsCommitTpl->vin[n].scriptWitness.stack[0] = *utxo.m_sig; - } - else { - mFundsCommitTpl->vin.emplace_back(uint256S(utxo.m_txid), utxo.m_nout); - if (utxo.m_sig) - mFundsCommitTpl->vin[n].scriptWitness.stack.push_back(*utxo.m_sig); - else - mFundsCommitTpl->vin[n].scriptWitness.stack.emplace_back(64); - } - ++n; - } - } - return *mFundsCommitTpl; -} - -CMutableTransaction SwapInscriptionBuilder::MakeFundsCommitTx() const -{ - CMutableTransaction commit_tx = GetFundsCommitTxTemplate(); - - CAmount funds_required = ParseAmount(GetMinFundingAmount()); - CAmount funds_provided = 0; - for (const auto &utxo: m_funds) { - funds_provided += utxo.m_amount; - } - - CAmount change = funds_provided - funds_required; - - if(change > Dust(*m_mining_fee_rate)) { - commit_tx.vout[1].scriptPubKey = (CScript() << 1 << *m_swap_script_pk_B); - commit_tx.vout[1].nValue = change; - } else { - commit_tx.vout.pop_back(); - - funds_required = ParseAmount(GetMinFundingAmount()); // Calculate again since one output was removed - } - - if(funds_provided < funds_required) { - throw l15::TransactionError("funds amount too small"); - } - - commit_tx.vout[0].scriptPubKey = CScript() << 1 << get<0>(FundsCommitTapRoot()); - if (commit_tx.vout.size() == 2) { //has a change: commit just what required - commit_tx.vout[0].nValue = CalculateOutputAmount(funds_required, *m_mining_fee_rate, commit_tx); - } - else { // has no change: commit whole amount from inputs - commit_tx.vout[0].nValue = CalculateOutputAmount(funds_provided, *m_mining_fee_rate, commit_tx); - } - - return commit_tx; -} - -const CMutableTransaction &SwapInscriptionBuilder::GetFundsCommitTx() const -{ - if (!mFundsCommitTx) { - mFundsCommitTx = MakeFundsCommitTx(); - } - return *mFundsCommitTx; -} - - -void SwapInscriptionBuilder::SignFundsCommitment(uint32_t n, const std::string& sk) -{ - CheckContractTerms(FUNDS_TERMS); - - if (n >= m_funds.size()) - throw ContractTermWrongValue((std::ostringstream() << name_funds << '[' << n << "]: " << n << ">= size: " << m_funds.size()).str()); - - auto funds_it = m_funds.begin(); - std::advance(funds_it, n); - - core::ChannelKeys keypair(unhex(sk)); - - if (!funds_it->m_pubkey) - throw ContractTermMissing((std::ostringstream() << name_funds << '[' << n << "].pubkey").str()); - if (keypair.GetLocalPubKey() != funds_it->m_pubkey) - throw ContractValueMismatch((std::ostringstream() << name_funds << '[' << n << "].pubkey").str()); - - if (!m_funds_unspendable_key_factor) - m_funds_unspendable_key_factor = core::ChannelKeys::GetStrongRandomKey(keypair.Secp256k1Context()); - - std::clog << "Signing input#" << n << std::endl; - - CMutableTransaction commit_tx = MakeFundsCommitTx(); - - std::vector spent_outs; - for (const auto& utxo: m_funds) { - spent_outs.emplace_back(utxo.m_amount, CScript() << 1 << *utxo.m_pubkey); - } - - funds_it->m_sig = keypair.SignTaprootTx(commit_tx, n, std::vector(spent_outs), {}); - commit_tx.vin[n].scriptWitness.stack[0] = *funds_it->m_sig; -} - -void SwapInscriptionBuilder::SignFundsSwap(const std::string& sk) -{ - CheckContractTerms(MARKET_PAYOFF_SIG); - - core::ChannelKeys keypair(unhex(sk)); - - if (keypair.GetLocalPubKey() != *m_swap_script_pk_B) { - throw ContractError("Swap PubKey does not match the secret"); - } - - auto utxo_pubkeyscript = CScript() << 1 << (*m_ord_pk); - - const CMutableTransaction& funds_commit = GetFundsCommitTx(); - CMutableTransaction swap_tx(MakeSwapTx(true)); - - m_funds_swap_sig_B = keypair.SignTaprootTx(swap_tx, 1, {CTxOut(*m_ord_amount, utxo_pubkeyscript), funds_commit.vout[0]}, MakeFundsSwapScript(*m_swap_script_pk_B, *m_swap_script_pk_M)); -} - -void SwapInscriptionBuilder::SignFundsPayBack(const std::string& sk) -{ - const CMutableTransaction& funds_commit = GetFundsCommitTx(); // Request it here in order to force reuired fields check - - core::ChannelKeys keypair(unhex(sk)); - - auto commit_taproot = FundsCommitTapRoot(); - //auto commit_pubkeyscript = CScript() << 1 << get<0>(commit_taproot); - auto payoff_pubkeyscript = CScript() << 1 << *m_swap_script_pk_B; - - xonly_pubkey internal_unspendable_key = core::ChannelKeys::CreateUnspendablePubKey(*m_funds_unspendable_key_factor); - - CScript& payback_script = get<2>(commit_taproot).GetScripts()[1]; - - auto commit_scriptpath = get<2>(commit_taproot).CalculateScriptPath(payback_script); - bytevector control_block = {static_cast(0xc0 | get<1>(commit_taproot))}; - control_block.reserve(1 + internal_unspendable_key.size() + commit_scriptpath.size() * uint256::size()); - control_block.insert(control_block.end(), internal_unspendable_key.begin(), internal_unspendable_key.end()); - for(uint256 &branch_hash : commit_scriptpath) - control_block.insert(control_block.end(), branch_hash.begin(), branch_hash.end()); - - CMutableTransaction payback_tx; - payback_tx.vin = {CTxIn(funds_commit.GetHash(), 0, {}, GetCsvInBlocks(12))}; - payback_tx.vin.front().scriptWitness.stack.emplace_back(64); - payback_tx.vin.front().scriptWitness.stack.emplace_back(payback_script.begin(), payback_script.end()); - payback_tx.vin.front().scriptWitness.stack.emplace_back(control_block); - payback_tx.vout = {CTxOut(0, payoff_pubkeyscript)}; - payback_tx.vout.front().nValue = CalculateOutputAmount(funds_commit.vout[0].nValue, *m_mining_fee_rate, payback_tx); - - signature payback_sig = keypair.SignTaprootTx(payback_tx, 0, {funds_commit.vout[0]}, payback_script); - payback_tx.vin.front().scriptWitness.stack.front() = move(payback_sig); - - mFundsPaybackTx = move(payback_tx); -} - -void SwapInscriptionBuilder::MarketSignOrdPayoffTx(const std::string& sk) -{ - CheckContractTerms(MARKET_PAYOFF_TERMS); - - core::ChannelKeys keypair(unhex(sk)); - if (keypair.GetLocalPubKey() != *m_swap_script_pk_M) { - throw ContractError("Swap PubKey does not match the secret"); - } - - CScript transfer_pubkeyscript = CScript() << 1 << *m_swap_script_pk_B; - - CMutableTransaction swap_tx(MakeSwapTx(true)); - - CMutableTransaction transfer_tx; - - transfer_tx.vin = {CTxIn(swap_tx.GetHash(), 0)}; - transfer_tx.vin.front().scriptWitness.stack.emplace_back(64); - transfer_tx.vout = {CTxOut(swap_tx.vout[0].nValue, move(transfer_pubkeyscript))}; - transfer_tx.vout.front().nValue = CalculateOutputAmount(swap_tx.vout[0].nValue, *m_mining_fee_rate, transfer_tx); - - m_ordpayoff_sig = keypair.SignTaprootTx(transfer_tx, 0, {swap_tx.vout[0]}, {}); - - transfer_tx.vin.front().scriptWitness.stack.front() = *m_ordpayoff_sig; - - mOrdPayoffTx = move(transfer_tx); -} - -void SwapInscriptionBuilder::MarketSignSwap(const std::string& sk) -{ - CheckContractTerms(FUNDS_SWAP_SIG); - - core::ChannelKeys keypair(unhex(sk)); - - if (keypair.GetLocalPubKey() != m_swap_script_pk_M.value()) { - throw ContractError("Swap PubKey does not match the secret"); - } - - auto utxo_pubkeyscript = CScript() << 1 << *m_ord_pk; - - CMutableTransaction swap_tx(MakeSwapTx(true)); - - m_funds_swap_sig_M = keypair.SignTaprootTx(swap_tx, 1, {CTxOut(*m_ord_amount, utxo_pubkeyscript), GetFundsCommitTx().vout[0]}, MakeFundsSwapScript(*m_swap_script_pk_B, *m_swap_script_pk_M)); - - swap_tx.vin[1].scriptWitness.stack[0] = *m_funds_swap_sig_M; - - mSwapTx = move(swap_tx); - - PrecomputedTransactionData txdata; - txdata.Init(*mSwapTx, {CTxOut(*m_ord_amount, utxo_pubkeyscript), GetFundsCommitTx().vout[0]}, /* force=*/ true); - - const CTxIn& ordTxin = mSwapTx->vin.at(0); - MutableTransactionSignatureChecker TxOrdChecker(&(*mSwapTx), 0, *m_ord_amount, txdata, MissingDataBehavior::FAIL); - bool ordPath = VerifyScript(ordTxin.scriptSig, utxo_pubkeyscript, &ordTxin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TxOrdChecker); - if (!ordPath) { - throw ContractError("Ord path swap error"); - } - - const CTxIn& txin = mSwapTx->vin.at(1); - MutableTransactionSignatureChecker tx_checker(&(*mSwapTx), 1, GetFundsCommitTx().vout[0].nValue, txdata, MissingDataBehavior::FAIL); - bool fundsPath = VerifyScript(txin.scriptSig, GetFundsCommitTx().vout[0].scriptPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, tx_checker); - if (!fundsPath) { - throw ContractError("Funds path swap error"); - } -} - -string SwapInscriptionBuilder::FundsCommitRawTransaction() const -{ - std::string res = EncodeHexTx(CTransaction(GetFundsCommitTx())); - return res; -} - -string SwapInscriptionBuilder::FundsPayBackRawTransaction() -{ - if (!mFundsPaybackTx) { - throw std::logic_error("FundsPayOff transaction data unavailable"); - } - std::string res = EncodeHexTx(CTransaction(*mFundsPaybackTx)); - return res; -} - -string SwapInscriptionBuilder::OrdSwapRawTransaction() const -{ - std::string res = EncodeHexTx(CTransaction(GetSwapTx())); - return res; -} - -string SwapInscriptionBuilder::OrdPayoffRawTransaction() const -{ - std::string res = EncodeHexTx(CTransaction(GetPayoffTx())); - return res; -} - -string SwapInscriptionBuilder::Serialize(SwapPhase phase) -{ - CheckContractTerms(phase); - - UniValue contract(UniValue::VOBJ); - - contract.pushKV(name_version, m_protocol_version); - contract.pushKV(name_ord_price, UniValue(FormatAmount(m_ord_price))); - contract.pushKV(name_swap_script_pk_M, hex(*m_swap_script_pk_M)); - - if (phase == ORD_TERMS || phase == ORD_SWAP_SIG || phase == MARKET_PAYOFF_SIG || phase == MARKET_SWAP_SIG) { - - } - if (phase == ORD_SWAP_SIG || phase == MARKET_PAYOFF_SIG || phase == MARKET_SWAP_SIG) { - contract.pushKV(name_ord_txid, *m_ord_txid); - contract.pushKV(name_ord_nout, *m_ord_nout); - contract.pushKV(name_ord_amount, FormatAmount(*m_ord_amount)); - contract.pushKV(name_ord_pk, hex(*m_ord_pk)); - contract.pushKV(name_swap_script_pk_A, hex(*m_swap_script_pk_A)); - } - if (phase == ORD_SWAP_SIG || phase == MARKET_PAYOFF_SIG || phase == MARKET_SWAP_SIG) { - contract.pushKV(name_ord_swap_sig_A, hex(*m_ord_swap_sig_A)); - } - - if (phase == FUNDS_TERMS || phase == FUNDS_COMMIT_SIG || phase == MARKET_PAYOFF_SIG || phase == FUNDS_SWAP_SIG || phase == MARKET_SWAP_SIG) { - contract.pushKV(name_market_fee, UniValue(FormatAmount(*m_market_fee))); - contract.pushKV(name_mining_fee_rate, UniValue(FormatAmount(*m_mining_fee_rate))); - } - if (phase == FUNDS_COMMIT_SIG || phase == MARKET_PAYOFF_SIG || phase == FUNDS_SWAP_SIG || phase == MARKET_SWAP_SIG) { - UniValue funds(UniValue::VARR); - for (const auto& utxo: m_funds) { - UniValue utxo_val(UniValue::VOBJ); - - utxo_val.pushKV(name_funds_txid, utxo.m_txid); - utxo_val.pushKV(name_funds_nout, utxo.m_nout); - utxo_val.pushKV(name_funds_amount, FormatAmount(utxo.m_amount)); - utxo_val.pushKV(name_funds_commit_sig, hex(*utxo.m_sig)); - - funds.push_back(move(utxo_val)); - } - contract.pushKV(name_funds, move(funds)); - - contract.pushKV(name_funds_unspendable_key_factor, hex(*m_funds_unspendable_key_factor)); - contract.pushKV(name_swap_script_pk_B, hex(*m_swap_script_pk_B)); - } - - if (phase == MARKET_PAYOFF_SIG) { - contract.pushKV(name_ordpayoff_sig, hex(*m_ordpayoff_sig)); - } - - if (phase == FUNDS_SWAP_SIG || phase == MARKET_SWAP_SIG) { - contract.pushKV(name_funds_swap_sig_B, hex(*m_funds_swap_sig_B)); - } - - if (phase == MARKET_SWAP_SIG) { - contract.pushKV(name_funds_swap_sig_M, hex(*m_funds_swap_sig_M)); - } - - UniValue dataRoot(UniValue::VOBJ); - dataRoot.pushKV(name_contract_type, val_swap_inscription); - dataRoot.pushKV(name_params, move(contract)); - - return dataRoot.write(); -} - -void SwapInscriptionBuilder::CheckContractTerms(SwapPhase phase) const -{ - switch (phase) { - case MARKET_SWAP_SIG: - if (!m_funds_swap_sig_M) throw ContractTermMissing("Market funds sig"); - // no break; - case FUNDS_SWAP_SIG: - if (!m_funds_swap_sig_B) throw ContractTermMissing("Funds seller sig"); - // no break; - case MARKET_PAYOFF_SIG: - if (!m_ordpayoff_sig) throw ContractTermMissing("Ord pay-off sig"); - // no break; - case MARKET_PAYOFF_TERMS: - CheckContractTerms(FUNDS_COMMIT_SIG); - case ORD_SWAP_SIG: - if (!m_ord_swap_sig_A) throw ContractTermMissing("Ord seller sig"); - if (!m_ord_pk) throw ContractTermMissing("Ord UTXO pubkey"); - if (!m_ord_amount) throw ContractTermMissing("Ord UTXO amount"); - if (!m_ord_txid) throw ContractTermMissing("Ord UTXO txid"); - if (!m_ord_nout) throw ContractTermMissing("Ord UTXO nout"); - if (!m_swap_script_pk_A) throw ContractTermMissing("Ord seller pubkey"); - // no break; - case ORD_TERMS: - if (m_ord_price <= 0) throw ContractTermMissing("Ord price"); - if (!m_swap_script_pk_M) throw ContractTermMissing("Market swap pubkey"); - break; - case FUNDS_COMMIT_SIG: - if (m_funds.empty()) throw ContractTermMissing("Funds UTXO"); - { - CAmount funds_amount = 0; - for (const auto& utxo: m_funds) { - funds_amount += utxo.m_amount; - - if (!utxo.m_sig) throw ContractTermMissing("Funds commit sig"); - } - if (funds_amount < ParseAmount(GetMinFundingAmount())) throw ContractTermMissing("Funds UTXO amount not enough"); - } - if (!m_swap_script_pk_B) throw ContractTermMissing("Ord buyer pubkey"); - if (!m_funds_unspendable_key_factor) throw ContractTermMissing("Funds commit unspendable key factor"); - // no break; - case FUNDS_TERMS: - if (m_ord_price <= 0) throw ContractTermMissing("Ord price"); - if (!m_market_fee) throw ContractTermMissing("Market fee"); - if (!m_mining_fee_rate) throw ContractTermMissing("Mining fee rate"); - if (!m_swap_script_pk_M) throw ContractTermMissing("Market pubkey"); - break; - } - - switch (phase) { - case MARKET_SWAP_SIG: - case FUNDS_SWAP_SIG: - CheckFundsSwapSig(); - case MARKET_PAYOFF_SIG: - CheckOrdPayoffSig(); - case MARKET_PAYOFF_TERMS: - case ORD_SWAP_SIG: - CheckOrdSwapSig(); - case ORD_TERMS: - break; - case FUNDS_COMMIT_SIG: - case FUNDS_TERMS: - break; - } -} - -void SwapInscriptionBuilder::Deserialize(const string &data) -{ - UniValue root; - root.read(data); - - if (root[name_contract_type].get_str() != val_swap_inscription) { - throw ContractProtocolError("SwapInscription contract does not match " + root[name_contract_type].getValStr()); - } - - const UniValue& contract = root[name_params]; - - if (contract[name_version].getInt() != m_protocol_version) { - throw ContractProtocolError("Wrong SwapInscription contract version: " + contract[name_version].getValStr()); - } - - if (m_ord_price) { - if (m_ord_price != ParseAmount(contract[name_ord_price].getValStr())) throw ContractValueMismatch(std::string(name_ord_price)); - } else - m_ord_price = ParseAmount(contract[name_ord_price].getValStr()); - - { const auto &val = contract[name_market_fee]; - if (!val.isNull()) { - if (m_market_fee) { - if (*m_market_fee != ParseAmount(val.getValStr())) throw ContractValueMismatch(std::string(name_market_fee)); - } - m_market_fee = ParseAmount(val.getValStr()); - } - } - { const auto& val = contract[name_swap_script_pk_A]; - if (!val.isNull()) { - if (m_swap_script_pk_A) { - if (*m_swap_script_pk_A != unhex(val.get_str())) throw ContractValueMismatch(std::string(name_swap_script_pk_A)); - } - else m_swap_script_pk_A = unhex(val.get_str()); - } - } - { const auto& val = contract[name_swap_script_pk_B]; - if (!val.isNull()) { - if (m_swap_script_pk_B) { - if (*m_swap_script_pk_B != unhex(val.get_str())) throw ContractValueMismatch(std::string(name_swap_script_pk_B)); - } - else m_swap_script_pk_B = unhex(val.get_str()); - } - } - { const auto& val = contract[name_swap_script_pk_M]; - if (!val.isNull()) { - if (m_swap_script_pk_M) { - if (*m_swap_script_pk_M != unhex(val.get_str())) throw ContractValueMismatch(std::string(name_swap_script_pk_M)); - } - else m_swap_script_pk_M = unhex(val.get_str()); - } - } - { const auto& val = contract[name_ord_txid]; - if (!val.isNull()) { - if (m_ord_txid) { - if (*m_ord_txid != val.get_str()) throw ContractValueMismatch(std::string(name_ord_txid)); - } - else m_ord_txid = val.get_str(); - } - } - { const auto& val = contract[name_ord_nout]; - if (!val.isNull()) { - if (m_ord_nout) { - if (*m_ord_nout != val.getInt()) throw ContractValueMismatch(std::string(name_ord_nout)); - } - else m_ord_nout = val.getInt(); - } - } - { const auto& val = contract[name_ord_amount]; - if (!val.isNull()) { - if (m_ord_amount) { - if (*m_ord_amount != ParseAmount(val.getValStr())) throw ContractValueMismatch(std::string(name_ord_amount)); - } - else m_ord_amount = ParseAmount(val.getValStr()); - } - } - { const auto& val = contract[name_ord_pk]; - if (!val.isNull()) { - if (m_ord_pk) { - if (*m_ord_pk != unhex(val.get_str())) throw ContractValueMismatch(std::string(name_ord_txid)); - } - else m_ord_pk = unhex(val.get_str()); - } - } - { const auto& val = contract[name_funds_unspendable_key_factor]; - if (!val.isNull()) { - if (m_funds_unspendable_key_factor) { - if (*m_funds_unspendable_key_factor != unhex(val.get_str())) throw ContractValueMismatch(std::string(name_funds_unspendable_key_factor)); - } - else m_funds_unspendable_key_factor = unhex(val.get_str()); - } - } - { const auto& val = contract[name_funds]; - if (!val.isNull()) { - if (!val.isArray()) throw ContractTermWrongFormat(std::string(name_funds)); - if (!m_funds.empty() && m_funds.size() != val.size()) throw ContractValueMismatch(std::string(name_funds) + " size"); - - auto utxo_it = m_funds.begin(); - for (size_t i = 0; i < val.size(); ++i) { - const auto &txid_val = val[i][name_funds_txid]; - //std::format("{}[{}].{}", name_funds, i, name_funds_txid) - if (txid_val.isNull()) - throw ContractTermMissing((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_txid).str()); - - const auto &nout_val = val[i][name_funds_nout]; - //std::format("{}[{}].{}", name_funds, i, name_funds_nout) - if (nout_val.isNull()) - throw ContractTermMissing((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_nout).str()); - - const auto &amount_val = val[i][name_funds_amount]; - // std::format("{}[{}].{}", name_funds, i, name_funds_amount) - if (amount_val.isNull()) - throw ContractTermMissing((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_amount).str()); - - const auto &sig_val = val[i][name_funds_commit_sig]; - if (sig_val.isNull()) - throw ContractTermMissing((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_commit_sig).str()); - - if (i == m_funds.size()) { - m_funds.emplace_back(txid_val.get_str(), - nout_val.getInt(), - ParseAmount(amount_val.getValStr()), - xonly_pubkey(), - unhex(sig_val.get_str())); - } - else { - // std::format("{}[{}].{}", name_funds, i, name_funds_txid) - if (utxo_it->m_txid != txid_val.get_str()) - throw ContractValueMismatch((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_txid).str()); - // std::format("{}[{}].{}", name_funds, i, name_funds_nout) - if (utxo_it->m_nout != nout_val.getInt()) - throw ContractValueMismatch((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_nout).str()); - // std::format("{}[{}].{}", name_funds, i, name_funds_amount) - if (utxo_it->m_amount != ParseAmount(amount_val.getValStr())) - throw ContractValueMismatch((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_amount).str()); - if (utxo_it->m_sig) { - // std::format("{}[{}].{}", name_funds, i, name_funds_commit_sig - if (*utxo_it->m_sig != unhex(sig_val.get_str())) - throw ContractValueMismatch((std::ostringstream() << name_funds << '[' << i << "]." << name_funds_commit_sig).str()); - } - else utxo_it->m_sig = unhex(sig_val.get_str()); - - ++utxo_it; - } - } - } - } - { const auto& val = contract[name_mining_fee_rate]; - if (!val.isNull()) { - if (m_mining_fee_rate) { - if (*m_mining_fee_rate != ParseAmount(val.getValStr())) throw ContractError(std::string(name_mining_fee_rate)); - } - else m_mining_fee_rate = ParseAmount(val.getValStr()); - } - } - { const auto& val = contract[name_ord_swap_sig_A]; - if (!val.isNull()) { - if (m_ord_swap_sig_A) { - if (*m_ord_swap_sig_A != unhex(val.get_str())) throw ContractError(std::string(name_ord_swap_sig_A)); - } - else m_ord_swap_sig_A = unhex(val.get_str()); - } - } - { const auto& val = contract[name_funds_swap_sig_B]; - if (!val.isNull()) { - if (m_funds_swap_sig_B) { - if (*m_funds_swap_sig_B != unhex(val.get_str())) throw ContractError(std::string(name_funds_swap_sig_B)); - } - else m_funds_swap_sig_B = unhex(val.get_str()); - } - } - { const auto& val = contract[name_funds_swap_sig_M]; - if (!val.isNull()) { - if (m_funds_swap_sig_M) { - if (*m_funds_swap_sig_M != unhex(val.get_str())) throw ContractError(std::string(name_funds_swap_sig_M)); - } - else m_funds_swap_sig_M = unhex(val.get_str()); - } - } - { const auto& val = contract[name_ordpayoff_sig]; - if (!val.isNull()) { - if (m_ordpayoff_sig) { - if (*m_ordpayoff_sig != unhex(val.get_str())) throw ContractError(std::string(name_ordpayoff_sig)); - } - else m_ordpayoff_sig = unhex(val.get_str()); - } - } -} - - -const CMutableTransaction &SwapInscriptionBuilder::GetSwapTx() const -{ - if (!mSwapTx) { - mSwapTx.emplace(MakeSwapTx(true)); - } - return *mSwapTx; -} - -const CMutableTransaction &SwapInscriptionBuilder::GetPayoffTx() const -{ - if (!mOrdPayoffTx) { - - CScript transfer_pubkeyscript = CScript() << 1 << *m_swap_script_pk_B; - - CMutableTransaction swap_tx(MakeSwapTx(true)); - - CMutableTransaction transfer_tx = CreatePayoffTxTemplate(); - - transfer_tx.vin[0].prevout.hash = swap_tx.GetHash(); - transfer_tx.vin[0].prevout.n = 0; - transfer_tx.vin[0].scriptWitness.stack[0] = *m_ordpayoff_sig; - - transfer_tx.vout[0].scriptPubKey = move(transfer_pubkeyscript); - transfer_tx.vout[0].nValue = CalculateOutputAmount(swap_tx.vout[0].nValue, *m_mining_fee_rate, transfer_tx); - - mOrdPayoffTx = move(transfer_tx); - } - return *mOrdPayoffTx; -} - -std::vector> SwapInscriptionBuilder::GetTransactions() const { - return { - { *m_mining_fee_rate, CreatePayoffTxTemplate() }, - { *m_mining_fee_rate, GetSwapTxTemplate() }, - { *m_mining_fee_rate, GetFundsCommitTxTemplate() } - }; -} - -SwapInscriptionBuilder &SwapInscriptionBuilder::OrdUTXO(const string &txid, uint32_t nout, const string &amount) -{ - m_ord_txid = txid; - m_ord_nout = nout; - m_ord_amount = ParseAmount(amount); - return *this; -} - -SwapInscriptionBuilder &SwapInscriptionBuilder::AddFundsUTXO(const string &txid, uint32_t nout, const string &amount, const std::string& pk) -{ - m_funds.emplace_back(txid, nout, ParseAmount(amount), unhex(pk)); - return *this; -} - -CMutableTransaction SwapInscriptionBuilder::CreatePayoffTxTemplate() const { - CMutableTransaction result; - CScript pubKeyScript = CScript() << 1 << xonly_pubkey(); - - result.vin = {CTxIn(uint256(0), 0)}; - result.vin.front().scriptWitness.stack.push_back(signature()); - result.vout = {CTxOut(0, move(pubKeyScript))}; - result.vout.front().nValue = 0; - - return result; -} - - -void SwapInscriptionBuilder::CheckOrdSwapSig() const -{ - bool has_funds_sig = m_funds_unspendable_key_factor && m_funds_swap_sig_B && m_funds_swap_sig_M; - - auto ord_scriptpubkey = CScript() << 1 << *m_ord_pk; - - std::vector spent_outs = {CTxOut(*m_ord_amount, ord_scriptpubkey)}; - if (has_funds_sig) { - spent_outs.emplace_back(GetFundsCommitTx().vout.front()); - } - - if (mSwapTx) { - VerifyTxSignature(*m_ord_pk, *m_ord_swap_sig_A, *mSwapTx, 0, move(spent_outs), {}); - } - else { - CMutableTransaction swap_tx(MakeSwapTx(has_funds_sig)); - VerifyTxSignature(*m_ord_pk, *m_ord_swap_sig_A, swap_tx, 0, move(spent_outs), {}); - } -} - -std::string SwapInscriptionBuilder::GetMinFundingAmount() const -{ - return FormatAmount(m_ord_price + *m_market_fee + CalculateWholeFee()); -} - -void SwapInscriptionBuilder::CheckFundsSwapSig() const -{ - auto ord_scriptpubkey = CScript() << 1 << *m_ord_pk; - std::vector spent_outs = {CTxOut(*m_ord_amount, ord_scriptpubkey), GetFundsCommitTx().vout.front()}; - - if (mSwapTx) { - VerifyTxSignature(*m_swap_script_pk_B, *m_funds_swap_sig_B, *mSwapTx, 1, move(spent_outs), MakeFundsSwapScript(*m_swap_script_pk_B, *m_swap_script_pk_M)); - } - else { - CMutableTransaction swap_tx(MakeSwapTx(true)); - VerifyTxSignature(*m_swap_script_pk_B, *m_funds_swap_sig_B, swap_tx, 1, move(spent_outs), MakeFundsSwapScript(*m_swap_script_pk_B, *m_swap_script_pk_M)); - } -} - -void SwapInscriptionBuilder::CheckOrdPayoffSig() const -{ - if (mSwapTx) { - VerifyTxSignature(*m_swap_script_pk_M, *m_ordpayoff_sig, GetPayoffTx(), 0, {mSwapTx->vout.front()}, {}); - } - else { - CMutableTransaction swap_tx(MakeSwapTx(true)); - VerifyTxSignature(*m_swap_script_pk_M, *m_ordpayoff_sig, GetPayoffTx(), 0, {swap_tx.vout.front()}, {}); - } -} - - -} // namespace l15::inscribeit diff --git a/src/inscribeit/swap_inscription.hpp b/src/inscribeit/swap_inscription.hpp deleted file mode 100644 index af20102..0000000 --- a/src/inscribeit/swap_inscription.hpp +++ /dev/null @@ -1,163 +0,0 @@ -#pragma once - -#include - -#include "script_merkle_tree.hpp" - -#include "contract_builder.hpp" - -namespace l15::inscribeit { - -enum SwapPhase { - ORD_TERMS, - FUNDS_TERMS, - FUNDS_COMMIT_SIG, - MARKET_PAYOFF_TERMS, - MARKET_PAYOFF_SIG, - ORD_SWAP_SIG, - FUNDS_SWAP_SIG, - MARKET_SWAP_SIG, -}; - -class SwapInscriptionBuilder : public ContractBuilder -{ - CAmount m_whole_fee = 0; - CAmount m_last_fee_rate = 0; - - static const uint32_t m_protocol_version; - - CAmount m_ord_price; - std::optional m_market_fee; - - std::optional m_swap_script_pk_A; - std::optional m_swap_script_pk_B; - std::optional m_swap_script_pk_M; - - std::optional m_ord_txid; - std::optional m_ord_nout; - std::optional m_ord_amount; - std::optional m_ord_pk; - - std::list m_funds; - - std::optional m_funds_unspendable_key_factor; - - std::optional m_ord_swap_sig_A; - - std::optional m_funds_swap_sig_B; - std::optional m_funds_swap_sig_M; - - std::optional m_ordpayoff_sig; - - mutable std::optional mFundsCommitTpl; - mutable std::optional mFundsPaybackTpl; - - mutable std::optional mSwapTpl; - mutable std::optional mOrdPayoffTpl; - - mutable std::optional mFundsCommitTx; - mutable std::optional mFundsPaybackTx; - - mutable std::optional mSwapTx; - mutable std::optional mOrdPayoffTx; - - std::tuple FundsCommitTapRoot() const; - - CMutableTransaction MakeSwapTx(bool with_funds_in) const; - - void CheckOrdSwapSig() const; - void CheckFundsSwapSig() const; - - void CheckOrdPayoffSig() const; - - std::tuple FundsCommitTemplateTapRoot() const; -protected: - std::vector> GetTransactions() const override; - -public: - CMutableTransaction CreatePayoffTxTemplate() const; - CMutableTransaction GetSwapTxTemplate() const; - - CMutableTransaction& GetFundsCommitTxTemplate() const; - CMutableTransaction MakeFundsCommitTx() const; - const CMutableTransaction& GetFundsCommitTx() const; - - const CMutableTransaction& GetSwapTx() const; - const CMutableTransaction& GetPayoffTx() const; - - static const std::string name_ord_price; - static const std::string name_market_fee; - - static const std::string name_swap_script_pk_A; - static const std::string name_swap_script_pk_B; - static const std::string name_swap_script_pk_M; - - static const std::string name_ord_txid; - static const std::string name_ord_nout; - static const std::string name_ord_amount; - static const std::string name_ord_pk; - - static const std::string name_funds; - static const std::string name_funds_unspendable_key_factor; - static const std::string name_funds_txid; - static const std::string name_funds_nout; - static const std::string name_funds_amount; - - static const std::string name_funds_commit_sig; - - static const std::string name_ord_swap_sig_A; - - static const std::string name_funds_swap_sig_B; - static const std::string name_funds_swap_sig_M; - - static const std::string name_ordpayoff_unspendable_key_factor; - static const std::string name_ordpayoff_sig; - - explicit SwapInscriptionBuilder(): m_ord_price(0), m_market_fee(0) {} - - SwapInscriptionBuilder(const SwapInscriptionBuilder&) = default; - SwapInscriptionBuilder(SwapInscriptionBuilder&&) noexcept = default; - - explicit SwapInscriptionBuilder(const std::string& ord_price, const std::string& market_fee); - - SwapInscriptionBuilder& operator=(const SwapInscriptionBuilder& ) = default; - SwapInscriptionBuilder& operator=(SwapInscriptionBuilder&& ) noexcept = default; - - uint32_t GetProtocolVersion() const override { return m_protocol_version; } - - SwapInscriptionBuilder& MiningFeeRate(const std::string& fee_rate) { SetMiningFeeRate(fee_rate); return *this; } - SwapInscriptionBuilder& OrdUTXO(const std::string& txid, uint32_t nout, const std::string& amount); - SwapInscriptionBuilder& AddFundsUTXO(const std::string& txid, uint32_t nout, const std::string& amount, const std::string& pk); - - SwapInscriptionBuilder& SwapScriptPubKeyA(const std::string& v) { m_swap_script_pk_A = unhex(v); return *this; } - SwapInscriptionBuilder& SwapScriptPubKeyB(const std::string& v) { m_swap_script_pk_B = unhex(v); return *this; } - - std::string GetSwapScriptPubKeyA() const { return hex(m_swap_script_pk_A.value()); } - std::string GetSwapScriptPubKeyB() const { return hex(m_swap_script_pk_B.value()); } - - std::string GetSwapScriptPubKeyM() const { return hex(m_swap_script_pk_M.value()); } - void SetSwapScriptPubKeyM(const std::string& v) { m_swap_script_pk_M = unhex(v); } - - void SignOrdSwap(const std::string& sk); - - void SignFundsCommitment(uint32_t n, const std::string& sk); - void SignFundsSwap(const std::string& sk); - void SignFundsPayBack(const std::string& sk); - - void MarketSignOrdPayoffTx(const std::string& sk); - void MarketSignSwap(const std::string& sk); - - void CheckContractTerms(SwapPhase phase) const; - std::string Serialize(SwapPhase phase); - void Deserialize(const std::string& data); - - std::string FundsCommitRawTransaction() const; - std::string FundsPayBackRawTransaction(); - - std::string OrdSwapRawTransaction() const; - std::string OrdPayoffRawTransaction() const; - - std::string GetMinFundingAmount() const override; -}; - -} // namespace l15::inscribeit diff --git a/src/python_binding/Makefile.am b/src/python_binding/Makefile.am deleted file mode 100644 index de6552a..0000000 --- a/src/python_binding/Makefile.am +++ /dev/null @@ -1,45 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/primitives \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/core \ - -I$(top_srcdir)/contrib/cex \ - -I$(top_srcdir)/src/inscribeit \ - -I$(top_srcdir)/src/python_binding \ -$(PYTHON_CPPFLAGS) $(PYTHON_INCLUDES) - -SWIG_FLAGS = -stdstl -SWIG_SOURCES = l15-core-pybind.i -SWIG_PYTHON_MODULE = libl15-core-pybind-wrap.cxx -CLEANFILES = $(SWIG_PYTHON_MODULE) libl15-core-pybind.py - -BUILT_SOURCES = $(SWIG_PYTHON_MODULE) -EXTRA_DIST = $(SWIG_SOURCES) - -$(SWIG_PYTHON_MODULE): $(SWIG_SOURCES) $(top_srcdir)/src/inscribeit/contract_error.hpp $(top_srcdir)/src/common/common_error.hpp $(top_srcdir)/src/core/transaction.hpp - $(SWIG) -I$(top_srcdir)/src/common -I$(top_srcdir)/src/core -I$(top_srcdir)/src/inscribeit -I$(top_srcdir)/node/src -I$(top_srcdir)/node/src/primitives -I$(top_srcdir)/node/src/script -c++ -python -o $@ $< - - -lib_LTLIBRARIES = _libl15_core_pybind.la - -_libl15_core_pybind_la_SOURCES = $(SWIG_PYTHON_MODULE) $(SWIG_SOURCES_CPP) -_libl15_core_pybind_la_LDFLAGS = -shared -module -avoid-version $(PYTHON_LDFLAGS) -Wl,--no-undefined - -_libl15_core_pybind_la_LIBADD = \ - $(top_builddir)/src/core/libl15-core.la \ - $(top_builddir)/src/common/libl15-common.la \ - $(top_builddir)/node/src/secp256k1/libsecp256k1.la \ - $(top_builddir)/node/src/libbitcoinconsensus.la \ - $(top_builddir)/node/src/libunivalue.la \ - $(top_builddir)/src/inscribeit/libl15-inscribeit.la \ - $(PYTHON_LIBS) - -install-completed-library: - cp $(srcdir)/__init__.py $(top_builddir)/src/python_binding/ - cp $(top_builddir)/src/python_binding/.libs/_libl15_core_pybind.so $(top_builddir)/src/python_binding/_libl15_core_pybind.so - diff --git a/src/python_binding/Readme.md b/src/python_binding/Readme.md deleted file mode 100644 index 0037130..0000000 --- a/src/python_binding/Readme.md +++ /dev/null @@ -1,230 +0,0 @@ -# L15 python module - -__TOC__ - -## Importing example - -```python -import sys -sys.path.append("...path/to/module/directory...") -import libl15_core_pybind as l15 - -print(l15.Version()) -``` - -# Module libl15_core_pybind - -## `CreateInscriptionBuilder(chain_mode: str) -> libl15_core_pybind.CreateInscriptionBuilder` -Creates instance of `CreateInscriptionBuilder` class -*Parameters:* - - `chain_mode: str` - is a mode of blockchain. Must be one of the following values: `mainnet`, `testnet`, `regtest`, otherwise will raise an exception - -## Class `CreateInscriptionBuilder` -This class is responsible for creation of an inscription - -### `GetProtocolVersion() -> int` -Returns protocol version. This field is required for further enhancements - -### `GetUtxoTxId() -> str` -Accessor for UTXO identifier - -### `SetUtxoTxId(v: str)` -Sets UTXO identifier for the inscription to be built - -*Parameters:* - - `v: str` - is a UTXO identifier - -### `GetUtxoNOut() -> int` -Accessor for previously set UTXO transaction output number - -### `SetUtxoNOut(v: int)` -Sets UTXO transaction output number for the inscription - -*Parameters:* - - `v: int` - is an UTXO output number - -### `GetUtxoAmount() -> str` -Returns amount of bitcoin previously set for the inscription. Looks like a price of inscription - -### `SetUtxoAmount(v: str)` -Sets amount of bitcoin for the inscription. Looks like a price of inscription - -*Parameters:* - - `v: str` - is an amount in bitcoins - -### `GetContentType() -> str` -Returns content type previously set for theinscription - -### `SetContentType(v: str)` -Sets content type for the inscription - -*Parameters:* - - `v: str` - is a content type - -### `GetContent() -> str` -Returns hex representation of content previously set for the inscription - -### `SetContent(v: str)` -Sets content for inscription - -*Parameters:* - - `v: str` - is a hex-encoded content - -### `GetDestinationPubKey() -> str` -Returns hex representation of destination public key previously set for the inscription - -### `SetDestinationPubKey(v: str)` -Sets destination public key for the inscription - -*Parameters:* - - `v: str` - is a hex-encoded destination public key - -### `GetIntermediateSecKey(v: str) -> str` -std::string GetIntermediateSecKey() const { return l15::hex(m_inscribe_taproot_sk.value()); } - -### `UTXO(txid: str, nout: int, amount: str) -> CreateInscriptionBuilder` -This is a convenience method which sets three parameters of inscription simultaneously - -*Parameters:* -- `txid: str` - is a UTXO identifier -- `nout: int` - is a UTXO output number -- `amount: str` - is an amount in bitcoins - -*Returns:* - Reference to itself, which allows to chain method calls - -### `Data(content_type: str, hex_data: str) -> CreateInscriptionBuilder` -This is a convenience method which parameters of inscription content - -*Parameters:* -- `content_type: str` - is a content type -- `hex_data: str` - is a hex-encoded content - -*Returns:* -Reference to itself, which allows to chain method calls - -### `FeeRate(rate: str) -> CreateInscriptionBuilder` -Sets fee rate for inscription transactions - -*Parameters:* -- `rate: str` - is a fee rate - -*Returns:* -Reference to itself, which allows to chain method calls - -### `Destination(pk: str) -> CreateInscriptionBuilder` -Sets inscription destination public key - -*Parameters:* -- `pk: str` - is a destination public key - -*Returns:* -Reference to itself, which allows to chain method calls - -### `IntermediateTaprootPrivKey() -> str` -Returns taproot private key -Needed in case of a fallback scenario to return funds - -### `GetUtxoPubKey() -> str` -Returns hex-encoded UTXO public key - -### `GetUtxoSig() -> str` -Returns hex-encoded UTXO signature key - -### `GetInscribeScriptPubKey() -> str` -Returns hex-encoded inscription script public key - -### `GetInscribeScriptSig() -> str` -Returns hex-encoded inscription script signature - -### `GetInscribeInternaltPubKey() -> str` -Returns hex-encoded inscription internal public key - -### `Sign(utxo_sk: str)` -Checks arguments set for the inscription. Creates funding and genesis transactions - -### `std::vector RawTransactions() -> List[str]` -Returns funding and genesis transactions - -### `Serialize() -> str` -Returns JSON-serialized inscription creation data - -### `Deserialize(data: str)` -Parses JSON-serialized inscription creation data, sets it to the builder and recreates transactions - -*Parameters:* -- `data: str` - is a JSON data - -## Examples - -### C++ Example -```c++ -ChannelKeys utxo_key(w->wallet().Secp256k1Context()); -ChannelKeys dest_key(w->wallet().Secp256k1Context()); - -//create address from key pair -string addr = w->btc().Bech32Encode(utxo_key.GetLocalPubKey()); - -//send to the address -string txid = w->btc().SendToAddress(addr, "1"); - -auto prevout = w->btc().CheckOutput(txid, addr); - -std::string fee_rate = "0.00005"; - -//CHECK_NOTHROW(fee_rate = w->btc().EstimateSmartFee("1")); - -std::clog << "Fee rate: " << fee_rate << std::endl; - -CreateInscriptionBuilder builder("regtest"); - -builder.SetUtxoTxId(get<0>(prevout).hash.GetHex()); -builder.SetUtxoNOut(get<0>(prevout).n); -builder.SetUtxoAmount("1"); -builder.SetMiningFeeRate(fee_rate); -builder.SetContentType("text"); -builder.SetContent(hex(std::string("test"))); -builder.SetDestinationPubKey(hex(dest_key.GetLocalPubKey())); -builder.Sign(hex(utxo_key.GetLocalPrivKey())) - -std::string ser_data; -ser_data = builder.Serialize(); - -std::clog << ser_data << std::endl; - -CreateInscriptionBuilder builder2("regtest"); - -builder2.Deserialize(ser_data); - -stringvector rawtx; -rawtx = builder2.RawTransactions(); - -CMutableTransaction funding_tx, genesis_tx; -DecodeHexTx(funding_tx, rawtx.front()); -DecodeHexTx(genesis_tx, rawtx.back()); - -w->btc().SpendTx(CTransaction(funding_tx)); -w->btc().SpendTx(CTransaction(genesis_tx)); -``` - -### Python example -```python -import sys -from binascii import hexlify - -sys.path.append("...path/to/module/directory...") - -import libl15_core_pybind as l15 - -try: - builder = l15.CreateInscriptionBuilder("regtest") - - builder.UTXO("abcdefgh", 1, "1").\ - Data("text", hexlify("content".encode()).decode()).\ - FeeRate("0.00005").\ - Sign("34234234") - - data = builder.Serialize() -except Exception as e: - print("Exception: ", e.args[0]) -``` \ No newline at end of file diff --git a/src/python_binding/__init__.py b/src/python_binding/__init__.py deleted file mode 100644 index 32d53fd..0000000 --- a/src/python_binding/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - # __init__.py -from .libl15_core_pybind import * diff --git a/src/python_binding/l15-core-pybind.i b/src/python_binding/l15-core-pybind.i deleted file mode 100644 index 03b441a..0000000 --- a/src/python_binding/l15-core-pybind.i +++ /dev/null @@ -1,115 +0,0 @@ -%module libl15_core_pybind - -%include "std_shared_ptr.i" -%include "std_string.i" -%include "std_vector.i" -%include "std_map.i" -%include "exception.i" - -%apply unsigned int { uint32_t } -%apply unsigned long long { uint64_t } - -%template(StringVector) std::vector; -%template(SharedL15Error) std::shared_ptr; - -%{ - -#include "transaction.hpp" -#include "create_inscription.hpp" -#include "swap_inscription.hpp" -#include "common_error.hpp" - -const std::string build_time = __DATE__ " " __TIME__; - -const std::string Version() { - return build_time; -} -%} - -%exception { - try { - $action - } catch (l15::Error& e) { - PyErr_SetString(PyExc_Exception, (std::string(e.what()) + ": " + e.details()).c_str()); - SWIG_fail; - } catch (std::exception& e) { - PyErr_SetString(PyExc_Exception, e.what()); - SWIG_fail; - } -} - -%typemap(out) CMutableTransaction (PyObject* obj) -%{ - obj = PyDict_New(); - - { - PyObject *txid = PyUnicode_FromString($1.GetHash().GetHex().c_str()); - PyDict_SetItemString(obj, "txid", txid); - Py_XDECREF(txid); - } - - { - PyObject *inputs = PyList_New($1.vin.size()); - for (size_t i = 0;i < $1.vin.size();++i) { - PyObject *in = PyDict_New(); - - { - PyObject *hash = PyString_FromString($1.vin[i].prevout.hash.GetHex().c_str()); - PyDict_SetItemString(in, "txid", hash); - Py_XDECREF(hash); - } - - { - PyObject *n = PyInt_FromLong($1.vin[i].prevout.n); - PyDict_SetItemString(in, "vout", n); - Py_XDECREF(n); - } - - PyList_SET_ITEM(inputs, i, in); - } - PyDict_SetItemString(obj, "vin", inputs); - Py_XDECREF(inputs); - } - - { - PyObject* outputs = PyList_New($1.vout.size()); - for (size_t i = 0; i < $1.vout.size(); ++i) { - PyObject* out = PyDict_New(); - - { - PyObject* val = PyLong_FromLongLong($1.vout[i].nValue); - PyDict_SetItemString(out, "value", val); - Py_XDECREF(val); - } - - { - PyObject* n = PyInt_FromLong(i); - PyDict_SetItemString(out, "n", n); - Py_XDECREF(n); - } - - if (l15::core::IsTaproot($1.vout[i])) { - PyObject *scriptpubkey = PyString_FromString(l15::core::GetTaprootPubKey($1.vout[i]).c_str()); - PyDict_SetItemString(out, "pubKey", scriptpubkey); - Py_XDECREF(scriptpubkey); - } - - PyList_SET_ITEM(outputs, i, out); - } - PyDict_SetItemString(obj, "vout", outputs); - Py_XDECREF(outputs); - } - - $result = SWIG_Python_AppendOutput($result, obj); -%} - -%include "common_error.hpp" -%include "contract_error.hpp" -%include "create_inscription.hpp" -%include "swap_inscription.hpp" -%include "transaction.hpp" -%include "transaction.h" - -%inline %{ - const std::string Version(); -%} diff --git a/src/service/Makefile.am b/src/service/Makefile.am index 700e1f8..3a73bf5 100644 --- a/src/service/Makefile.am +++ b/src/service/Makefile.am @@ -1,15 +1,15 @@ AM_CPPFLAGS = $(ZMQ_CPPFLAGS) \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/contrib/secp256k1/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/core \ -I$(top_srcdir)/src/api \ - -I$(top_srcdir)/src/p2p \ + -I$(top_srcdir)/src/p2p \ -I$(top_srcdir)/contrib/cex @@ -21,6 +21,8 @@ libl15_srv_la_SOURCES = \ onchain_protocol.cpp \ storage_service.cpp \ generic_service.cpp \ - signer_service.cpp \ zmq_context.cpp +if BUILD_FROST +libl15_srv_la_SOURCES += signer_service.cpp +endif \ No newline at end of file diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 15424ce..2c70717 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/contrib/secp256k1/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/contrib/cex \ -I$(top_srcdir)/contrib/cli11 \ -I$(top_srcdir)/src/common \ diff --git a/src/wasm_binding/Makefile.am b/src/wasm_binding/Makefile.am deleted file mode 100644 index 69b1c9f..0000000 --- a/src/wasm_binding/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ - -AM_CPPFLAGS = -DWASM_MODULE \ - -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/core \ - -I$(top_srcdir)/src/inscribeit \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/contrib/cli11 \ - -I$(top_srcdir)/contrib/cex \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support - - -AM_LDFLAGS=-L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto --post-js inscribeit.js - - -L15_LIBS = \ -$(top_builddir)/src/core/libl15-core.la \ -$(top_builddir)/src/common/libl15-common.la \ -$(top_builddir)/node/src/libbitcoinconsensus.la \ -$(top_builddir)/contrib/secp256k1/libsecp256k1.la \ -$(top_builddir)/node/src/libunivalue.la \ -$(top_builddir)/src/inscribeit/libl15-inscribeit.la - -BUILT_SOURCES = inscribeit.cpp inscribeit.js -EXTRA_DIST = inscribeit.idl - -CLEANFILES = $(BUILT_SOURCES) l15.wasm - -inscribeit.js: inscribeit.idl - -inscribeit.cpp: inscribeit.idl - webidl_binder $< inscribeit - -l15.cpp: inscribeit.cpp - -bin_PROGRAMS = l15.js - -l15_js_SOURCES = l15.cpp -l15_js_LDADD = $(L15_LIBS) diff --git a/src/wasm_binding/inscribeit.idl b/src/wasm_binding/inscribeit.idl deleted file mode 100644 index fb06abb..0000000 --- a/src/wasm_binding/inscribeit.idl +++ /dev/null @@ -1,83 +0,0 @@ - - -[Prefix="std::"] -interface string -{ - void string([Const] DOMString str); - [Const] DOMString c_str(); -}; - -[Prefix="l15::wasm::"] -interface ChannelKeys -{ - static void InitSecp256k1(); - - void ChannelKeys(); - void ChannelKeys([Const] DOMString sk); - [Value] string GetLocalPrivKey(); - [Value] string GetLocalPubKey(); - [Value] string SignSchnorr([Const] DOMString m); -}; - -[Prefix="l15::wasm::"] -interface Exception -{ - [Value] static string getMessage(any e); -}; - -[Prefix="l15::inscribeit::"] -interface CreateInscriptionBuilder -{ - void CreateInscriptionBuilder([Const] DOMString ord_amount); - [Ref] CreateInscriptionBuilder MiningFeeRate([Const] DOMString rate); - [Ref] CreateInscriptionBuilder AddUTXO([Const] DOMString txid, long nout, [Const] DOMString amount, [Const] DOMString pubkey); - [Ref] CreateInscriptionBuilder Data([Const] DOMString content_type, [Const] DOMString hex_data); - [Ref] CreateInscriptionBuilder DestinationPubKey([Const] DOMString pk); - [Ref] CreateInscriptionBuilder AddToCollection([Const] DOMString collection_id, [Const] DOMString txid, long nout, [Const] DOMString amount); - - void SignCommit(long n, [Const] DOMString sk, [Const] DOMString script_pubkey); - void SignCollection([Const] DOMString sk); - void SignInscription([Const] DOMString script_sk); - - [Value] string Serialize(); - - [Value] string getIntermediateTaprootSK(); - - [Value] string GetMinFundingAmount(); -}; - -enum SwapPhase -{ - "ORD_TERMS", - "FUNDS_TERMS", - "FUNDS_COMMIT_SIG", - "MARKET_PAYOFF_TERMS", - "MARKET_PAYOFF_SIG", - "ORD_SWAP_SIG", - "FUNDS_SWAP_SIG", - "MARKET_SWAP_SIG", -}; - -[Prefix="l15::inscribeit::"] -interface SwapInscriptionBuilder -{ - void SwapInscriptionBuilder([Const] DOMString ord_price, [Const] DOMString market_fee); - - [Ref] SwapInscriptionBuilder OrdUTXO([Const] DOMString txid, long nout, [Const] DOMString amount); - [Ref] SwapInscriptionBuilder AddFundsUTXO([Const] DOMString txid, long nout, [Const] DOMString amount, [Const] DOMString pubkey); - - [Ref] SwapInscriptionBuilder SwapScriptPubKeyA([Const] DOMString v); - [Ref] SwapInscriptionBuilder SwapScriptPubKeyB([Const] DOMString v); - - void SignOrdSwap([Const] DOMString sk); - - void SignFundsCommitment(long funds_index, [Const] DOMString sk); - void SignFundsSwap([Const] DOMString sk); - void SignFundsPayBack([Const] DOMString sk); - - void CheckContractTerms(SwapPhase phase); - [Value] string Serialize(SwapPhase phase); - void Deserialize([Const] DOMString data); - - [Value] string GetMinFundingAmount(); -}; \ No newline at end of file diff --git a/src/wasm_binding/l15.cpp b/src/wasm_binding/l15.cpp deleted file mode 100644 index a419285..0000000 --- a/src/wasm_binding/l15.cpp +++ /dev/null @@ -1,71 +0,0 @@ - -#include "random.h" - -#include "common.hpp" -#include "channel_keys.hpp" -#include "create_inscription.hpp" -#include "swap_inscription.hpp" - - -namespace { - -secp256k1_context * CreateSecp256k1() { - RandomInit(); - secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY); - std::vector> vseed(32); - GetRandBytes(vseed); - int ret = secp256k1_context_randomize(ctx, vseed.data()); - assert(ret); - return ctx; -} - -const secp256k1_context * GetSecp256k1() -{ - static secp256k1_context *ctx = CreateSecp256k1(); - return ctx; -} - -} - -namespace l15::wasm { - -class ChannelKeys : private l15::core::ChannelKeys -{ -public: - static void InitSecp256k1() - { GetSecp256k1(); } - - ChannelKeys() : l15::core::ChannelKeys(GetSecp256k1()) - {} - - explicit ChannelKeys(const char* sk) : l15::core::ChannelKeys(GetSecp256k1(), l15::unhex(sk)) - {} - - std::string GetLocalPrivKey() const - { return l15::hex(l15::core::ChannelKeys::GetLocalPrivKey()); } - - std::string GetLocalPubKey() const - { return l15::hex(l15::core::ChannelKeys::GetLocalPubKey()); } - - std::string SignSchnorr(const char* m) const - { return l15::hex(l15::core::ChannelKeys::SignSchnorr(uint256S(m))); } -}; - -struct Exception -{ - static std::string getMessage(void* exceptionPtr) - { - std::exception *e = reinterpret_cast(exceptionPtr); - if (l15::Error *l15err = dynamic_cast(e)) { - return std::string(l15err->what()) + ": " + l15err->details(); - } - return std::string(e->what()); - } -}; - -} - -using namespace l15; -using namespace l15::inscribeit; - -#include "inscribeit.cpp" diff --git a/test/Makefile.am b/test/Makefile.am index c4cdb8e..1f81718 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,17 +1,11 @@ SUBDIRS = -#if BUILD_APIS -#SUBDIRS += core p2p -#endif -# -#if BUILD_SERVICES -#SUBDIRS += service -#endif - -if BUILD_INSCRIBEIT -if !BUILD_PLUGIN_API -SUBDIRS += inscribeit +if BUILD_APIS +SUBDIRS += core p2p endif + +if BUILD_SERVICES +SUBDIRS += service endif if BUILD_TOOLS @@ -21,12 +15,12 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/contrib \ -I$(top_srcdir)/contrib/cex \ -I$(top_srcdir)/contrib/cli11 \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/p2p \ -I$(top_srcdir)/src/tools \ @@ -35,7 +29,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/service -AM_LDFLAGS=$(ZMQ_LDFLAGS) -L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto +AM_LDFLAGS=$(ZMQ_LDFLAGS) -L$(top_builddir)/$(NODE_PATH)/src -L$(top_builddir)/$(NODE_PATH)/src/crypto L15_LIBS = \ $(top_builddir)/src/service/libl15-srv.la \ @@ -44,11 +38,11 @@ $(top_builddir)/src/core/libl15-core.la \ $(top_builddir)/src/tools/libl15-tools.la \ $(top_builddir)/src/common/libl15-common.la \ -lbitcoin_common -lbitcoin_util -lbitcoin_consensus \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_base.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_avx2.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_x86_shani.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_sse41.la \ -$(top_builddir)/contrib/secp256k1/libsecp256k1.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_base.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_avx2.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_x86_shani.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_sse41.la \ +$(top_builddir)/$(SECP256K1_PATH)/libsecp256k1.la \ $(top_builddir)/node/src/libunivalue.la \ $(BOOST_FILESYSTEM_LIB) diff --git a/test/core/Makefile.am b/test/core/Makefile.am index 3f7482b..7d45def 100644 --- a/test/core/Makefile.am +++ b/test/core/Makefile.am @@ -4,12 +4,12 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/contrib \ -I$(top_srcdir)/contrib/cex \ -I$(top_srcdir)/contrib/cli11 \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/p2p \ -I$(top_srcdir)/src/tools \ @@ -17,7 +17,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/core -AM_LDFLAGS=-L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto +AM_LDFLAGS=-L$(top_builddir)/$(NODE_PATH)/src L15_LIBS = \ $(top_builddir)/src/api/libl15-api.la \ @@ -25,17 +25,25 @@ $(top_builddir)/src/core/libl15-core.la \ $(top_builddir)/src/tools/libl15-tools.la \ $(top_builddir)/src/common/libl15-common.la \ -lbitcoin_common -lbitcoin_util -lbitcoin_consensus \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_base.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_avx2.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_x86_shani.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_sse41.la \ -$(top_builddir)/contrib/secp256k1/libsecp256k1.la \ -$(top_builddir)/node/src/libunivalue.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_base.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_avx2.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_x86_shani.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_sse41.la \ +$(top_builddir)/$(NODE_PATH)/src/libunivalue.la \ +$(top_builddir)/$(SECP256K1_PATH)/libsecp256k1.la \ $(BOOST_FILESYSTEM_LIB) -bin_PROGRAMS = test_threshold_sign test_taptree test_taproot test_node +bin_PROGRAMS = test_taptree test_taproot test_node #test_ptlc +if BUILD_FROST + + bin_PROGRAMS += test_threshold_sign + + test_threshold_sign_SOURCES = test_threshold_sign.cpp + test_threshold_sign_LDADD = $(L15_LIBS) $(ZMQ_LDFLAGS) $(ZMQ_LIBS) + +endif test_taptree_SOURCES = test_taptree.cpp test_taptree_LDADD = $(L15_LIBS) @@ -52,6 +60,4 @@ test_taproot_LDADD = $(L15_LIBS) test_node_SOURCES = test_node.cpp test_node_LDADD = $(L15_LIBS) -test_threshold_sign_SOURCES = test_threshold_sign.cpp -test_threshold_sign_LDADD = $(L15_LIBS) $(ZMQ_LDFLAGS) $(ZMQ_LIBS) diff --git a/test/core/test_node.cpp b/test/core/test_node.cpp index ad006ab..3ecfdad 100644 --- a/test/core/test_node.cpp +++ b/test/core/test_node.cpp @@ -14,15 +14,17 @@ #include "chain_api.hpp" #include "channel_keys.hpp" +#include "test_case_wrapper.hpp" + using namespace l15; using namespace l15::core; const std::function G_TRANSLATION_FUN = nullptr; - -std::string configpath; +std::unique_ptr w; int main(int argc, char* argv[]) { + std::string configpath; Catch::Session session; @@ -53,84 +55,37 @@ int main(int argc, char* argv[]) configpath = (std::filesystem::current_path() / p).string(); } + w = std::make_unique(configpath, "l15node-cli"); + return session.run(); } - -struct TestConfigFactory -{ - Config conf; - explicit TestConfigFactory(const std::string& confpath) - { - std::clog << "Config: " << confpath << std::endl; - conf.ProcessConfig({"--conf=" + confpath}); - std::clog << "Config has been processed" << std::endl; - } - std::string GetDataDir() const - { - auto datadir_opt = conf.Subcommand(config::L15NODE).get_option(config::option::DATADIR); - if(!datadir_opt->empty()) - return datadir_opt->as(); - else - return std::string(); - } -}; - -struct TestcaseWrapper -{ - TestConfigFactory mConfFactory; - WalletApi wallet; - ChainApi node; - - explicit TestcaseWrapper() : - mConfFactory(configpath), - wallet(), - node(Bech32Coder(), std::move(mConfFactory.conf.ChainValues(config::L15NODE)), "l15node-cli") - { - StartNode(); - } - - ~TestcaseWrapper() - { - ExecHelper cli("l15node-cli", false); - StopNode(ChainMode::MODE_REGTEST, cli, conf().Subcommand(config::L15CLIENT)); - std::filesystem::remove_all(mConfFactory.GetDataDir() + "/regtest"); - } - - void StartNode() { - ExecHelper node("l15noded", false); - l15::StartNode(ChainMode::MODE_REGTEST, node, conf().Subcommand(config::L15NODE)); - } - - Config& conf() { return mConfFactory.conf; } -}; - -TEST_CASE_METHOD(TestcaseWrapper, "Start/stop l15-node") +TEST_CASE("Start/stop l15-node") { } -TEST_CASE_METHOD(TestcaseWrapper, "Test transactions") +TEST_CASE("Test transactions") { - ChannelKeys outkey(wallet.Secp256k1Context()); + ChannelKeys outkey; - ChannelKeys key(wallet.Secp256k1Context()); - std::string address = node.Bech32Encode(key.GetPubKey()); + ChannelKeys key; + std::string address = w->bech32().Encode(key.GetPubKey()); UniValue blocks; - blocks.read(node.GenerateToAddress(address, "1")); + blocks.read(w->btc().GenerateToAddress(address, "1")); UniValue block; - block.read(node.GetBlock(blocks[0].getValStr(), "1")); + block.read(w->btc().GetBlock(blocks[0].getValStr(), "1")); COutPoint out_point; CTxOut tx_out; - std::tie(out_point, tx_out) = node.CheckOutput(block["tx"][0].getValStr(), address); + std::tie(out_point, tx_out) = w->btc().CheckOutput(block["tx"][0].getValStr(), address); CHECK(tx_out.nValue == ParseAmount("4096")); CMutableTransaction op_return_tx; - op_return_tx.vin.emplace_back(CTxIn(out_point)); + op_return_tx.vin.emplace_back(out_point); CScript outpubkeyscript; outpubkeyscript << 1; @@ -140,14 +95,14 @@ TEST_CASE_METHOD(TestcaseWrapper, "Test transactions") outopreturnscript << OP_RETURN; outopreturnscript << ParseHex("db1ff3f207771e90ec30747525abaefd3b56ff2b3aecbb76809b7106617c442e"); - op_return_tx.vout.emplace_back(CTxOut(ParseAmount("4095.99"), outpubkeyscript)); - op_return_tx.vout.emplace_back(CTxOut(0, outopreturnscript)); + op_return_tx.vout.emplace_back(ParseAmount("4095.99"), outpubkeyscript); + op_return_tx.vout.emplace_back(0, outopreturnscript); - bytevector sig = wallet.SignTaprootTx(key.GetLocalPrivKey(), op_return_tx, 0, {tx_out}, {}); + bytevector sig = key.SignTaprootTx(op_return_tx, 0, {tx_out}, {}); op_return_tx.vin.front().scriptWitness.stack.emplace_back(sig); - node.GenerateToAddress(address, "100"); // Make coinbase tx mature + w->btc().GenerateToAddress(address, "100"); // Make coinbase tx mature - CHECK_NOTHROW(node.SpendTx(CTransaction(op_return_tx))); + CHECK_NOTHROW(w->btc().SpendTx(CTransaction(op_return_tx))); } diff --git a/test/core/test_taproot.cpp b/test/core/test_taproot.cpp index cb13ca3..82110ef 100644 --- a/test/core/test_taproot.cpp +++ b/test/core/test_taproot.cpp @@ -15,102 +15,20 @@ #include "utils.hpp" #include "script_merkle_tree.hpp" +#include "test_case_wrapper.hpp" + using namespace l15; using namespace l15::core; const std::function G_TRANSLATION_FUN = nullptr; -class TestcaseWrapper; -std::string configpath; std::unique_ptr w; -struct TestConfigFactory -{ - Config conf; - - explicit TestConfigFactory(const std::string &confpath) - { - conf.ProcessConfig({"--conf=" + confpath}); - } - - std::string GetBitcoinDataDir() const - { - auto datadir_opt = conf.Subcommand(config::BITCOIND).get_option(config::option::DATADIR); - if(!datadir_opt->empty()) - return datadir_opt->as(); - else - return std::string(); - } -}; - -struct TestcaseWrapper -{ - TestConfigFactory mConfFactory; - WalletApi mWallet; - ChainApi mBtc; - ExecHelper mCli; - ExecHelper mBtcd; -// channelhtlc_ptr mChannelForAliceSide; -// channelhtlc_ptr mChannelForCarolSide; - - explicit TestcaseWrapper() : - mConfFactory(configpath), - mWallet(), - mBtc(Bech32Coder(), std::move(mConfFactory.conf.ChainValues(config::BITCOIN)), "l15node-cli"), - mCli("l15node-cli", false), - mBtcd("bitcoind", false) - - { - StartBitcoinNode(); - - if(btc().GetChainHeight() < 50) - { - btc().CreateWallet("testwallet"); - btc().GenerateToAddress(btc().GetNewAddress(), "250"); - } - } - - virtual ~TestcaseWrapper() - { - StopBitcoinNode(); - std::filesystem::remove_all(mConfFactory.GetBitcoinDataDir() + "/regtest"); - } - - void StartBitcoinNode() - { - StartNode(ChainMode::MODE_REGTEST, mBtcd, conf().Subcommand(config::BITCOIND)); - } - - void StopBitcoinNode() - { - StopNode(ChainMode::MODE_REGTEST, mCli, conf().Subcommand(config::BITCOIN)); - } - - Config &conf() - { return mConfFactory.conf; } - - WalletApi &wallet() - { return mWallet; } - - ChainApi &btc() - { return mBtc; } -// ChannelHtlc& channel_for_alice() { return *mChannelForAliceSide; } -// ChannelHtlc& channel_for_carol() { return *mChannelForCarolSide; } - - void ResetMemPool() - { - StopBitcoinNode(); - - std::filesystem::remove(mConfFactory.GetBitcoinDataDir() + "/regtest/mempool.dat"); - - StartBitcoinNode(); - } - -}; int main(int argc, char* argv[]) { + std::string configpath; Catch::Session session; @@ -141,7 +59,7 @@ int main(int argc, char* argv[]) configpath = (std::filesystem::current_path() / p).string(); } - w = std::make_unique(); + w = std::make_unique(configpath, "bitcoin-cli"); return session.run(); } @@ -154,11 +72,11 @@ TEST_CASE("Taproot transaction test cases") SECTION("Taproot public key path spending") { //get key pair - auto sk = ChannelKeys(w->wallet().Secp256k1Context()); + ChannelKeys sk; auto& pk = sk.GetLocalPubKey(); //create address from key pair - string addr = w->btc().Bech32Encode(pk); + string addr = w->bech32().Encode(pk); //send to the address string txid = w->btc().SendToAddress(addr, "1.001"); @@ -170,7 +88,7 @@ TEST_CASE("Taproot transaction test cases") //spend first transaction to the last address - auto backpk = w->btc().Bech32Decode(backaddr); + auto backpk = w->bech32().Decode(backaddr); std::clog << "Payoff PK: " << HexStr(backpk) << std::endl; @@ -187,7 +105,7 @@ TEST_CASE("Taproot transaction test cases") std::vector prevtxouts = {std::get<1>(prevout)}; - bytevector sig = w->wallet().SignTaprootTx(sk.GetLocalPrivKey(), tx, 0, std::move(prevtxouts), {}); + bytevector sig = sk.SignTaprootTx(tx, 0, std::move(prevtxouts), {}); std::clog << "Signature: " << HexStr(sig) << std::endl; @@ -199,13 +117,13 @@ TEST_CASE("Taproot transaction test cases") SECTION("Taproot script path spending") { //get key pair Taproot - auto internal_sk = ChannelKeys(w->wallet().Secp256k1Context()); + ChannelKeys internal_sk; const auto& internal_pk = internal_sk.GetLocalPubKey(); std::clog << "\nInternal PK: " << HexStr(internal_pk) << std::endl; //get key pair script - auto sk = ChannelKeys(w->wallet().Secp256k1Context()); + ChannelKeys sk; const auto& pk = sk.GetLocalPubKey(); std::string pk_str = HexStr(pk); @@ -226,7 +144,7 @@ TEST_CASE("Taproot transaction test cases") uint8_t taprootpubkeyparity; std::tie(taprootpubkey, taprootpubkeyparity) = internal_sk.AddTapTweak(root); - string addr = w->btc().Bech32Encode(taprootpubkey); + string addr = w->bech32().Encode(taprootpubkey); std::clog << "\nTaproot PK: " << HexStr(taprootpubkey) << std::endl; std::clog << "Taptweak parity flag: " << (int)taprootpubkeyparity << std::endl; @@ -242,7 +160,7 @@ TEST_CASE("Taproot transaction test cases") //spend first transaction to the last address - auto backpk = w->btc().Bech32Decode(backaddr); + auto backpk = w->bech32().Decode(backaddr); std::clog << "Payoff PK: " << HexStr(backpk) << std::endl; @@ -259,7 +177,7 @@ TEST_CASE("Taproot transaction test cases") std::vector prevtxouts = {std::get<1>(prevout)}; - bytevector sig = w->wallet().SignTaprootTx(sk.GetLocalPrivKey(), tx, 0, std::move(prevtxouts), script); + bytevector sig = sk.SignTaprootTx(tx, 0, std::move(prevtxouts), script); std::clog << "Signature: " << HexStr(sig) << std::endl; diff --git a/test/core/test_taptree.cpp b/test/core/test_taptree.cpp index 93e9540..865263b 100644 --- a/test/core/test_taptree.cpp +++ b/test/core/test_taptree.cpp @@ -108,7 +108,7 @@ TEST_CASE("TapRoot single script") ScriptMerkleTree tap_tree (TreeBalanceType::WEIGHTED, {script}); uint256 root = tap_tree.CalculateRoot(); - auto tap_root = internal_sk.AddTapTweak(std::make_optional(root)); + auto tap_root = internal_sk.AddTapTweak(root); XOnlyPubKey xonly_internal_pubkey(internal_pk); diff --git a/test/inscribeit/Makefile.am b/test/inscribeit/Makefile.am deleted file mode 100644 index 64e0fda..0000000 --- a/test/inscribeit/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ - -AM_CPPFLAGS = \ - -I$(top_srcdir)/test \ - -I$(top_srcdir)/contrib \ - -I$(top_srcdir)/contrib/cex \ - -I$(top_srcdir)/contrib/cli11 \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ - -I$(top_srcdir)/src/common \ - -I$(top_srcdir)/src/p2p \ - -I$(top_srcdir)/src/tools \ - -I$(top_srcdir)/src/api \ - -I$(top_srcdir)/src/core \ - -I$(top_srcdir)/src/inscribeit - - -AM_LDFLAGS=-L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto - -L15_LIBS = \ -$(top_builddir)/src/inscribeit/libl15-inscribeit.la \ -$(top_builddir)/src/api/libl15-api.la \ -$(top_builddir)/src/core/libl15-core.la \ -$(top_builddir)/src/tools/libl15-tools.la \ -$(top_builddir)/src/common/libl15-common.la \ --lbitcoin_common -lbitcoin_util -lbitcoin_consensus \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_base.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_avx2.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_x86_shani.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_sse41.la \ -$(top_builddir)/node/src/secp256k1/libsecp256k1.la \ -$(top_builddir)/node/src/libunivalue.la \ -$(BOOST_FILESYSTEM_LIB) - -bin_PROGRAMS = test_create_inscription test_swap_inscription test_signing - -test_signing_SOURCES = test_signing.cpp -test_signing_LDADD = $(L15_LIBS) - -test_create_inscription_SOURCES = test_create_inscription.cpp -test_create_inscription_LDADD = $(L15_LIBS) - -test_swap_inscription_SOURCES = test_swap_inscription.cpp -test_swap_inscription_LDADD = $(L15_LIBS) - diff --git a/test/inscribeit/test_create_inscription.cpp b/test/inscribeit/test_create_inscription.cpp deleted file mode 100644 index 8c26cc1..0000000 --- a/test/inscribeit/test_create_inscription.cpp +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include - -#define CATCH_CONFIG_RUNNER -#include "catch/catch.hpp" - -#include "util/translation.h" -#include "config.hpp" -#include "nodehelper.hpp" -#include "chain_api.hpp" -#include "wallet_api.hpp" -#include "channel_keys.hpp" -#include "exechelper.hpp" -#include "create_inscription.hpp" -#include "core_io.h" -#include "serialize.h" - -#include "test_case_wrapper.hpp" - -using namespace l15; -using namespace l15::core; -using namespace l15::inscribeit; - -const std::function G_TRANSLATION_FUN = nullptr; - - -std::unique_ptr w; -std::optional> collection_out; -ChannelKeys collection_key; - -std::string GenRandomString(const int len) { - static const char alphanum[] = - "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - std::string tmp_s; - tmp_s.reserve(len); - - for (int i = 0; i < len; ++i) { - tmp_s += alphanum[rand() % (sizeof(alphanum) - 1)]; - } - - return tmp_s; -} - -int main(int argc, char* argv[]) -{ - std::string configpath; - Catch::Session session; - - - // Build a new parser on top of Catch's - using namespace Catch::clara; - auto cli - = session.cli() // Get Catch's composite command line parser - | Opt(configpath, "Config path") // bind variable to a new option, with a hint string - ["--config"] // the option names it will respond to - ("Path to L15 config"); - - session.cli(cli); - - // Let Catch (using Clara) parse the command line - int returnCode = session.applyCommandLine(argc, argv); - if(returnCode != 0) // Indicates a command line error - return returnCode; - - if(configpath.empty()) - { - std::cerr << "Bitcoin config is not passed!" << std::endl; - return 1; - } - - std::filesystem::path p(configpath); - if(p.is_relative()) - { - configpath = (std::filesystem::current_path() / p).string(); - } - - w = std::make_unique(configpath); - - return session.run(); -} - -struct CreateCondition -{ - std::vector funds; - bool collection_parent; -}; - -TEST_CASE("inscribe") -{ - //get key pair - ChannelKeys utxo_key; - ChannelKeys script_key; - bool added_to_collection = false; - - xonly_pubkey destination_pk = w->bech32().Decode(w->btc().GetNewAddress()); - - std::string fee_rate; - try { - fee_rate = w->btc().EstimateSmartFee("1"); - } - catch(...) { - fee_rate = "0.000011"; - } - - std::clog << "Fee rate: " << fee_rate << std::endl; - - std::string content_type = "text/ascii"; - auto content = hex(GenRandomString(1024)); - - CreateInscriptionBuilder builder("0.00002"); - CHECK_NOTHROW(builder.MiningFeeRate(fee_rate).Data(content_type, content)); - - std::clog << ">>>>> Estimate mining fee <<<<<" << std::endl; - - std::string exact_amount = builder.GetMinFundingAmount(); - - const CreateCondition parent = {{ParseAmount(exact_amount)}, true}; - const CreateCondition fund = {{10000}, false}; - const CreateCondition exact_fund = {{10000}, false}; - const CreateCondition multi_fund = {{8500, 1500}, false}; - const CreateCondition multi_fund_2 = {{7500, 1500, 1000}, false}; - - auto condition = GENERATE_REF(parent, fund, exact_fund, multi_fund, multi_fund_2); - - CHECK_NOTHROW(builder.DestinationPubKey(hex(condition.collection_parent ? collection_key.GetLocalPubKey() : destination_pk))); - - //create address from key pair - string addr = w->bech32().Encode(utxo_key.GetLocalPubKey()); - - for (CAmount amount: condition.funds) { - const std::string funds_amount = FormatAmount(amount); - - string funds_txid = w->btc().SendToAddress(addr, funds_amount); - auto prevout = w->btc().CheckOutput(funds_txid, addr); - - CHECK_NOTHROW(builder.AddUTXO(get<0>(prevout).hash.GetHex(), get<0>(prevout).n, funds_amount, hex(utxo_key.GetLocalPubKey()))); - } - - SECTION("Add to collection") - { - if (!condition.collection_parent) { - std::clog << ">>>>> collection id:" << get<0>(*collection_out) << std::endl; - const auto &col_utxo = get<1>(*collection_out); - CHECK_NOTHROW(builder.AddToCollection(get<0>(*collection_out), col_utxo.m_txid, col_utxo.m_nout, FormatAmount(col_utxo.m_amount))); - added_to_collection = true; - } - } - - std::clog << "Min funding: " << builder.GetMinFundingAmount() << "\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/" << std::endl; - - for (uint32_t n = 0; n < condition.funds.size(); ++n) { - std::clog << ">>>>> Sign commit <<<<<" << std::endl; - CHECK_NOTHROW(builder.SignCommit(n, hex(utxo_key.GetLocalPrivKey()), hex(script_key.GetLocalPubKey()))); - } - if (added_to_collection) { - std::clog << ">>>>> Sign collection <<<<<" << std::endl; - CHECK_NOTHROW(builder.SignCollection(hex(collection_key.GetLocalPrivKey()))); - } - std::clog << ">>>>> Sign inscription <<<<<" << std::endl; - CHECK_NOTHROW(builder.SignInscription(hex(script_key.GetLocalPrivKey()))); - - ChannelKeys rollback_key(unhex(builder.getIntermediateTaprootSK())); - - std::string ser_data; - CHECK_NOTHROW(ser_data = builder.Serialize()); - - std::clog << ser_data << std::endl; - - CreateInscriptionBuilder builder2("0.00002"); - - std::clog << ">>>>> Deserialize <<<<<" << std::endl; - CHECK_NOTHROW(builder2.Deserialize(ser_data)); - - stringvector rawtx; - CHECK_NOTHROW(rawtx = builder2.RawTransactions()); - - CMutableTransaction funding_tx; - CHECK(DecodeHexTx(funding_tx, rawtx.front())); - CHECK_NOTHROW(w->btc().SpendTx(CTransaction(funding_tx))); - - SECTION("Inscribe") - { - CMutableTransaction genesis_tx; - CHECK(DecodeHexTx(genesis_tx, rawtx.back())); - - LogTx(genesis_tx); - - std::string txid; - CHECK_NOTHROW(txid = w->btc().SpendTx(CTransaction(genesis_tx))); - - if (condition.collection_parent) { - std::string collection_id = txid + "i0"; - collection_out = {collection_id, {txid, 0, genesis_tx.vout.front().nValue, destination_pk}}; - } - else if (added_to_collection){ - get<1>(*collection_out).m_txid = txid; - get<1>(*collection_out).m_nout = 1; - } - } - - SECTION("Payback") - { - CScript rollbackpubkeyscript; - rollbackpubkeyscript << 1; - rollbackpubkeyscript << rollback_key.GetLocalPubKey(); - - CMutableTransaction rollback_tx; - rollback_tx.vin.emplace_back(COutPoint(funding_tx.GetHash(), 0)); - rollback_tx.vout.emplace_back(0, rollbackpubkeyscript); - - rollback_tx.vin.front().scriptWitness.stack.emplace_back(64); - - rollback_tx.vout.front().nValue = CalculateOutputAmount(funding_tx.vout.front().nValue, ParseAmount(fee_rate), rollback_tx); - - signature rollback_sig = rollback_key.SignTaprootTx(rollback_tx, 0, {funding_tx.vout.front()}, {}); - rollback_tx.vin.front().scriptWitness.stack.front() = static_cast(rollback_sig); - - CHECK_NOTHROW(w->btc().SpendTx(CTransaction(rollback_tx))); - } -} - - -TEST_CASE("NotEnoughAmount") -{ - //get key pair - ChannelKeys utxo_key; - ChannelKeys script_key; - ChannelKeys dest_key; - - //create address from key pair - string addr = w->bech32().Encode(utxo_key.GetLocalPubKey()); - - std::string fee_rate; - try { - fee_rate = w->btc().EstimateSmartFee("1"); - } - catch (...) { - fee_rate = "0.000011"; - } - std::clog << "Fee rate: " << fee_rate << std::endl; - - CreateInscriptionBuilder builder("0.00002"); - - std::string content_type = "text/ascii"; - auto content = hex(GenRandomString(1024)); - - CHECK_NOTHROW(builder.Data(content_type, content) - .MiningFeeRate(fee_rate)); - - std::string lesser_amount = FormatAmount(ParseAmount(builder.GetMinFundingAmount()) - 1); - - - string txid = w->btc().SendToAddress(addr, lesser_amount); - auto prevout = w->btc().CheckOutput(txid, addr); - - CHECK_NOTHROW(builder.AddUTXO(get<0>(prevout).hash.GetHex(), get<0>(prevout).n, lesser_amount, hex(utxo_key.GetLocalPubKey())) - .DestinationPubKey(hex(dest_key.GetLocalPubKey()))); - - CHECK_THROWS_AS(builder.SignCommit(0, hex(utxo_key.GetLocalPrivKey()), hex(script_key.GetLocalPubKey())), ContractError); - -} diff --git a/test/inscribeit/test_signing.cpp b/test/inscribeit/test_signing.cpp deleted file mode 100644 index 93a20b9..0000000 --- a/test/inscribeit/test_signing.cpp +++ /dev/null @@ -1,41 +0,0 @@ - -#include - -#define CATCH_CONFIG_MAIN -#include "catch/catch.hpp" - -#include "util/translation.h" - -#include "channel_keys.hpp" - -const std::function G_TRANSLATION_FUN = nullptr; - -using namespace l15; - -TEST_CASE("VerifySignature") -{ - const std::string pk_hex = "0a15a355a35e3181990f161bda0849022ffe5f53d331b9f989525e43633c9f67"; - const std::string challenge_hex = "2a845aeebbe5ebe3fe621ef6b13430bf0e22528e4ad72dbfff539d6cdbed6659"; - const std::string signature_hex = "128bdf69c469a23792b78f492d3444da9e7a5cc3276f09acb0f29d8a2314e7b1e0985448ea440c84ccb348a1bd1999011469b04c868e139daf53d3497034947f"; -// const std::string pk_hex = "d505e969f72a85c1b484d859e38188d1af63872d743b58e8bb3bdefe1ccd5396"; -// const std::string challenge_hex = "f7e6cc0f9549b34a7225391d965f2ad6ed04e4a641c9e675c7a4e5a11eb49da7"; -// const std::string signature_hex = "485e41ef0e4e7c33be3010275a4fc1852dda058e2a55179374a80ca7abddb5131146cd6e2838ed016fd0dd2f28aeacdbe53238af4e402fc051cc02fa83be65b4"; - - - l15::xonly_pubkey pk = l15::unhex(pk_hex); - - CHECK(pk.verify(l15::core::ChannelKeys::GetStaticSecp256k1Context(), unhex(signature_hex), uint256S(challenge_hex))); -} - -TEST_CASE("MakeSignature") -{ - const std::string challenge_hex = "2a845aeebbe5ebe3fe621ef6b13430bf0e22528e4ad72dbfff539d6cdbed6659"; - const seckey sk = unhex("76a2aa9d77b047b3b9822c6fabf90ccd0bbf511b3158184a6f13f90851cb76e2"); - core::ChannelKeys keypair(sk); - - signature sig = keypair.SignSchnorr(uint256S(challenge_hex)); - - xonly_pubkey pk = keypair.GetLocalPubKey(); - - CHECK(pk.verify(l15::core::ChannelKeys::GetStaticSecp256k1Context(), sig, uint256S(challenge_hex))); -} diff --git a/test/inscribeit/test_swap_inscription.cpp b/test/inscribeit/test_swap_inscription.cpp deleted file mode 100644 index a8921cf..0000000 --- a/test/inscribeit/test_swap_inscription.cpp +++ /dev/null @@ -1,401 +0,0 @@ -#include -#include -#include -#include - -#define CATCH_CONFIG_RUNNER -#include "catch/catch.hpp" - -#include "util/translation.h" -#include "config.hpp" -#include "nodehelper.hpp" -#include "chain_api.hpp" -#include "wallet_api.hpp" -#include "channel_keys.hpp" -#include "exechelper.hpp" -#include "swap_inscription.hpp" -#include "core_io.h" - -#include "policy/policy.h" - -#include "test_case_wrapper.hpp" - -using namespace l15; -using namespace l15::core; -using namespace l15::inscribeit; - -const std::function G_TRANSLATION_FUN = nullptr; - - -std::unique_ptr w; - - -int main(int argc, char* argv[]) -{ - std::string configpath; - Catch::Session session; - - - // Build a new parser on top of Catch's - using namespace Catch::clara; - auto cli - = session.cli() // Get Catch's composite command line parser - | Opt(configpath, "Config path") // bind variable to a new option, with a hint string - ["--config"] // the option names it will respond to - ("Path to L15 config"); - - session.cli(cli); - - // Let Catch (using Clara) parse the command line - int returnCode = session.applyCommandLine(argc, argv); - if(returnCode != 0) // Indicates a command line error - return returnCode; - - if(configpath.empty()) - { - std::cerr << "Bitcoin config is not passed!" << std::endl; - return 1; - } - - std::filesystem::path p(configpath); - if(p.is_relative()) - { - configpath = (std::filesystem::current_path() / p).string(); - } - - w = std::make_unique(configpath); - - return session.run(); -} - - -struct SwapCondition -{ - std::vector funds; - //CAmount funds; - bool has_change; -}; - -TEST_CASE("Swap") -{ - const std::string ORD_PRICE = "0.0001"; - const std::string MARKET_FEE = "0.00001"; - - ChannelKeys swap_script_key_A; - ChannelKeys swap_script_key_B; - ChannelKeys swap_script_key_M; - //get key pair - ChannelKeys ord_utxo_key; - ChannelKeys funds_utxo_key; - - std::string fee_rate; - try { - fee_rate = w->btc().EstimateSmartFee("1"); - } - catch(...) { - fee_rate = "0.00011"; - } - - // ORD side terms - //-------------------------------------------------------------------------- - - SwapInscriptionBuilder builderMarket(ORD_PRICE, MARKET_FEE); - builderMarket.SetSwapScriptPubKeyM(hex(swap_script_key_M.GetLocalPubKey())); - - string marketOrdConditions; - REQUIRE_NOTHROW(marketOrdConditions = builderMarket.Serialize(ORD_TERMS)); - - SwapInscriptionBuilder builderOrdSeller(ORD_PRICE, MARKET_FEE); - REQUIRE_NOTHROW(builderOrdSeller.Deserialize(marketOrdConditions)); - - REQUIRE_NOTHROW(builderOrdSeller.CheckContractTerms(ORD_TERMS)); - - //Create ord utxo - string ord_addr = w->bech32().Encode(ord_utxo_key.GetLocalPubKey()); - string ord_txid = w->btc().SendToAddress(ord_addr, "0.0001"); - auto ord_prevout = w->btc().CheckOutput(ord_txid, ord_addr); - - builderOrdSeller.OrdUTXO(get<0>(ord_prevout).hash.GetHex(), get<0>(ord_prevout).n, FormatAmount(get<1>(ord_prevout).nValue)); - builderOrdSeller.SwapScriptPubKeyA(hex(swap_script_key_A.GetLocalPubKey())); - - REQUIRE_NOTHROW(builderOrdSeller.SignOrdSwap(hex(ord_utxo_key.GetLocalPrivKey()))); - - string ordSellerTerms; - REQUIRE_NOTHROW(ordSellerTerms= builderOrdSeller.Serialize(ORD_SWAP_SIG)); - - - // FUNDS side terms - //-------------------------------------------------------------------------- - builderMarket.SetMiningFeeRate(fee_rate); - string marketFundsConditions = builderMarket.Serialize(FUNDS_TERMS); - - SwapInscriptionBuilder builderOrdBuyer(ORD_PRICE, MARKET_FEE); - builderOrdBuyer.Deserialize(marketFundsConditions); - - CAmount min_funding = ParseAmount(builderOrdBuyer.GetMinFundingAmount()); - CAmount dust = Dust(ParseAmount(fee_rate)); - - const SwapCondition fund_min_cond = {{min_funding}, false}; - const SwapCondition fund_min_3000_cond = {{min_funding + 3000}, true}; - const SwapCondition fund_min_dust_cond = {{min_funding+dust}, false}; - const SwapCondition fund_min_dust_1_cond = {{min_funding + dust + 1}, true}; - const SwapCondition fund_min_dust_100_cond = {{min_funding + dust - 100}, false}; - const SwapCondition fund_min_50_cond = {{min_funding + 50}, false}; - - const SwapCondition fund_min_3000_cond_2 = {{min_funding, 3000}, true}; - - auto condition = GENERATE_REF( - fund_min_cond, - fund_min_3000_cond, - fund_min_dust_cond, - fund_min_dust_1_cond, - fund_min_dust_100_cond, - fund_min_50_cond, - fund_min_3000_cond_2 - ); - - builderOrdBuyer.SwapScriptPubKeyB(hex(swap_script_key_B.GetLocalPubKey())); - - //Fund commitment - string funds_addr = w->bech32().Encode(funds_utxo_key.GetLocalPubKey()); - std::vector spent_outs; - - for (CAmount amount: condition.funds) { - const std::string funds_amount = FormatAmount(amount); - - string funds_txid = w->btc().SendToAddress(funds_addr, funds_amount); - auto funds_prevout = w->btc().CheckOutput(funds_txid, funds_addr); - - builderOrdBuyer.AddFundsUTXO(get<0>(funds_prevout).hash.GetHex(), get<0>(funds_prevout).n, funds_amount, hex(funds_utxo_key.GetLocalPubKey())); - spent_outs.emplace_back(ParseAmount(funds_amount), CScript() << 1 << funds_utxo_key.GetLocalPubKey()); - } - - for (size_t n = 0; n < condition.funds.size(); ++n) { - REQUIRE_NOTHROW(builderOrdBuyer.SignFundsCommitment(n, hex(funds_utxo_key.GetLocalPrivKey()))); - } - - auto commit_tx = builderOrdBuyer.GetFundsCommitTx(); - PrecomputedTransactionData txdata; - txdata.Init(commit_tx, move(spent_outs), true); - - for (uint32_t n = 0; n < commit_tx.vin.size(); ++n) { - const CTxIn &in = commit_tx.vin.at(n); - MutableTransactionSignatureChecker txChecker(&commit_tx, n, txdata.m_spent_outputs[n].nValue, txdata, MissingDataBehavior::FAIL); - bool res = VerifyScript(in.scriptSig, txdata.m_spent_outputs[n].scriptPubKey, &in.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, txChecker); - REQUIRE(res); - } - - - REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(builderOrdBuyer.GetFundsCommitTx()))); - - string ordBuyerTerms; - REQUIRE_NOTHROW(ordBuyerTerms = builderOrdBuyer.Serialize(FUNDS_COMMIT_SIG)); - - - // MARKET confirm terms - //-------------------------------------------------------------------------- - - REQUIRE_NOTHROW(builderMarket.Deserialize(ordSellerTerms)); - REQUIRE_NOTHROW(builderMarket.CheckContractTerms(ORD_SWAP_SIG)); - - REQUIRE_NOTHROW(builderMarket.Deserialize(ordBuyerTerms)); - REQUIRE_NOTHROW(builderMarket.CheckContractTerms(FUNDS_COMMIT_SIG)); - - string funds_commit_raw_tx; - REQUIRE_NOTHROW(funds_commit_raw_tx = builderMarket.FundsCommitRawTransaction()); - - CMutableTransaction funds_commit_tx; - REQUIRE(DecodeHexTx(funds_commit_tx, funds_commit_raw_tx)); - - REQUIRE(funds_commit_tx.vout.size() == (condition.has_change ? 2 : 1)); - - //REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(funds_commit_tx))); - -// SECTION("Funds PayBack") { -// REQUIRE_NOTHROW(builderOrdBuyer.SignFundsPayBack(hex(swap_script_key_B.GetLocalPrivKey()))); -// std::string funds_payback_raw_tx; -// REQUIRE_NOTHROW(funds_payback_raw_tx = builderOrdBuyer.FundsPayBackRawTransaction()); -// -// CMutableTransaction funds_payback_tx; -// REQUIRE(DecodeHexTx(funds_payback_tx, funds_payback_raw_tx)); -// -// w->btc().GenerateToAddress(w->btc().GetNewAddress(), "11"); -// REQUIRE_THROWS(w->btc().SpendTx(CTransaction(funds_payback_tx))); -// w->btc().GenerateToAddress(w->btc().GetNewAddress(), "1"); -// REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(funds_payback_tx))); -// -// } - SECTION("Execute Swap") { - w->btc().GenerateToAddress(w->btc().GetNewAddress(), "1"); - - REQUIRE_NOTHROW(builderMarket.MarketSignOrdPayoffTx(hex(swap_script_key_M.GetLocalPrivKey()))); - string ordMarketTerms; - REQUIRE_NOTHROW(ordMarketTerms = builderMarket.Serialize(MARKET_PAYOFF_SIG)); - - - // BUYER sign swap - //-------------------------------------------------------------------------- - - REQUIRE_NOTHROW(builderOrdBuyer.Deserialize(ordMarketTerms)); - REQUIRE_NOTHROW(builderOrdBuyer.CheckContractTerms(MARKET_PAYOFF_SIG)); - - REQUIRE_NOTHROW(builderOrdBuyer.SignFundsSwap(hex(swap_script_key_B.GetLocalPrivKey()))); - - string ordFundsSignature; - REQUIRE_NOTHROW(ordFundsSignature = builderOrdBuyer.Serialize(FUNDS_SWAP_SIG)); - - - // MARKET sign swap - //-------------------------------------------------------------------------- - - REQUIRE_NOTHROW(builderMarket.Deserialize(ordFundsSignature)); - REQUIRE_NOTHROW(builderMarket.MarketSignSwap(hex(swap_script_key_M.GetLocalPrivKey()))); - - string ord_swap_raw_tx = builderMarket.OrdSwapRawTransaction(); - string ord_transfer_raw_tx = builderMarket.OrdPayoffRawTransaction(); - - CMutableTransaction ord_swap_tx, ord_transfer_tx; - REQUIRE(DecodeHexTx(ord_swap_tx, ord_swap_raw_tx)); - REQUIRE(DecodeHexTx(ord_transfer_tx, ord_transfer_raw_tx)); - -// PrecomputedTransactionData txdata; -// txdata.Init(ord_swap_tx, {ord_commit_tx.vout[0], funds_commit_tx.vout[0]}, /* force=*/ true); -// -// const CTxIn& ordTxin = ord_swap_tx.vin.at(0); -// MutableTransactionSignatureChecker TxOrdChecker(&ord_swap_tx, 0, ord_commit_tx.vout[0].nValue, txdata, MissingDataBehavior::FAIL); -// bool ordPath = VerifyScript(ordTxin.scriptSig, ord_commit_tx.vout[0].scriptPubKey, &ordTxin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, TxOrdChecker); -// REQUIRE(ordPath); -// -// const CTxIn& txin = ord_swap_tx.vin.at(1); -// MutableTransactionSignatureChecker tx_checker(&ord_swap_tx, 1, funds_commit_tx.vout[0].nValue, txdata, MissingDataBehavior::FAIL); -// bool fundsPath = VerifyScript(txin.scriptSig, funds_commit_tx.vout[0].scriptPubKey, &txin.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, tx_checker); -// REQUIRE(fundsPath); - - REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(ord_swap_tx))); - REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(ord_transfer_tx))); - - w->btc().GenerateToAddress(w->btc().GetNewAddress(), "1"); - - - // BUYER spends his ord - //-------------------------------------------------------------------------- - - xonly_pubkey payoff_pk = w->bech32().Decode(w->btc().GetNewAddress()); - CScript buyer_pubkeyscript = CScript() << 1 << payoff_pk; - - CMutableTransaction ord_payoff_tx; - ord_payoff_tx.vin = {CTxIn(ord_transfer_tx.GetHash(), 0)}; - ord_payoff_tx.vin.front().scriptWitness.stack.emplace_back(64); - ord_payoff_tx.vout = {CTxOut(ord_transfer_tx.vout[0].nValue, buyer_pubkeyscript)}; - ord_payoff_tx.vout.front().nValue = CalculateOutputAmount(ord_transfer_tx.vout[0].nValue, ParseAmount(fee_rate), ord_payoff_tx); - - REQUIRE_NOTHROW(ord_payoff_tx.vin.front().scriptWitness.stack[0] = swap_script_key_B.SignTaprootTx(ord_payoff_tx, 0, {ord_transfer_tx.vout[0]}, {})); - - REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(ord_payoff_tx))); - - w->btc().GenerateToAddress(w->btc().GetNewAddress(), "1"); - - if (condition.has_change) { - // BUYER spends his change - //-------------------------------------------------------------------------- - - xonly_pubkey change_pk = w->bech32().Decode(w->btc().GetNewAddress()); - CScript buyer_change_pubkey_script = CScript() << 1 << change_pk; - - CMutableTransaction ord_change_spend_tx; - ord_change_spend_tx.vin = {CTxIn(funds_commit_tx.GetHash(), 1)}; - ord_change_spend_tx.vin.front().scriptWitness.stack.emplace_back(64); - ord_change_spend_tx.vout = {CTxOut(funds_commit_tx.vout[1].nValue, buyer_change_pubkey_script)}; - - - if (CalculateTxFee(ParseAmount(fee_rate), ord_change_spend_tx) > funds_commit_tx.vout[1].nValue + Dust(ParseAmount(fee_rate))) { - ord_change_spend_tx.vout.front().nValue = CalculateOutputAmount(funds_commit_tx.vout[1].nValue, ParseAmount(fee_rate), ord_change_spend_tx); - - REQUIRE_NOTHROW(ord_change_spend_tx.vin.front().scriptWitness.stack[0] = swap_script_key_B.SignTaprootTx(ord_change_spend_tx, 0, {funds_commit_tx.vout[1]}, {})); - REQUIRE_NOTHROW(w->btc().SpendTx(CTransaction(ord_change_spend_tx))); - } - - } - - w->btc().GenerateToAddress(w->btc().GetNewAddress(), "1"); - } -} - -TEST_CASE("FundsNotEnough") -{ - const std::string ORD_PRICE = "0.0001"; - const std::string MARKET_FEE = "0.00001"; - - ChannelKeys swap_script_key_A; - ChannelKeys swap_script_key_B; - ChannelKeys swap_script_key_M; - seckey preimage = ChannelKeys::GetStrongRandomKey(); - bytevector swap_hash(32); - CHash256().Write(preimage).Finalize(swap_hash); - //get key pair - ChannelKeys ord_utxo_key; - ChannelKeys funds_utxo_key; - - std::string fee_rate; - try { - fee_rate = w->btc().EstimateSmartFee("1"); - } - catch(...) { - fee_rate = "0.00011"; - } - std::clog << "Fee rate: " << fee_rate << std::endl; - - // ORD side terms - //-------------------------------------------------------------------------- - - SwapInscriptionBuilder builderMarket(ORD_PRICE, MARKET_FEE); - builderMarket.SetMiningFeeRate(fee_rate); - builderMarket.SetSwapScriptPubKeyM(hex(swap_script_key_M.GetLocalPubKey())); - - - string marketOrdConditions = builderMarket.Serialize(ORD_TERMS); - - SwapInscriptionBuilder builderOrdSeller(ORD_PRICE, MARKET_FEE); - builderOrdSeller.Deserialize(marketOrdConditions); - - builderOrdSeller.CheckContractTerms(ORD_TERMS); - - //Create ord utxo - string ord_addr = w->bech32().Encode(ord_utxo_key.GetLocalPubKey()); - string ord_txid = w->btc().SendToAddress(ord_addr, "0.0001"); - auto ord_prevout = w->btc().CheckOutput(ord_txid, ord_addr); - - builderOrdSeller.SwapScriptPubKeyA(hex(swap_script_key_A.GetLocalPubKey())); - builderOrdSeller.OrdUTXO(get<0>(ord_prevout).hash.GetHex(), get<0>(ord_prevout).n, "0.0001"); - - REQUIRE_NOTHROW(builderOrdSeller.SignOrdSwap(hex(swap_script_key_A.GetLocalPrivKey()))); - - string ordSellerTerms = builderOrdSeller.Serialize(ORD_SWAP_SIG); - - - // FUNDS side terms - //-------------------------------------------------------------------------- - - //builderMarket.SetMiningFeeRate(fee_rate); - string marketFundsConditions = builderMarket.Serialize(FUNDS_TERMS); - - SwapInscriptionBuilder builderOrdBuyer(ORD_PRICE, MARKET_FEE); - builderOrdBuyer.Deserialize(marketFundsConditions); - - //Create insufficient funds utxo - std::string funds_amount = FormatAmount(ParseAmount(builderOrdBuyer.GetMinFundingAmount()) - Dust(ParseAmount(fee_rate))); - std::string funds_addr = w->bech32().Encode(funds_utxo_key.GetLocalPubKey()); - std::string funds_txid = w->btc().SendToAddress(funds_addr, funds_amount); - - auto funds_prevout = w->btc().CheckOutput(funds_txid, funds_addr); - - builderOrdBuyer.SwapScriptPubKeyB(hex(swap_script_key_B.GetLocalPubKey())); - builderOrdBuyer.AddFundsUTXO(get<0>(funds_prevout).hash.GetHex(), get<0>(funds_prevout).n, funds_amount, hex(funds_utxo_key.GetLocalPubKey())); - REQUIRE_THROWS_AS(builderOrdBuyer.SignFundsCommitment(0, hex(funds_utxo_key.GetLocalPrivKey())), l15::TransactionError); - - //Create funds utxo -// funds_amount = builderOrdBuyer.GetMinFundingAmount(); -// -// builderOrdBuyer.FundsUTXO(get<0>(funds_prevout).hash.GetHex(), get<0>(funds_prevout).n, funds_amount); -// REQUIRE_NOTHROW(builderOrdBuyer.SignFundsCommitment(hex(funds_utxo_key.GetLocalPrivKey()))); -} diff --git a/test/p2p/Makefile.am b/test/p2p/Makefile.am index b12ba41..24b7b03 100644 --- a/test/p2p/Makefile.am +++ b/test/p2p/Makefile.am @@ -4,11 +4,11 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/contrib \ -I$(top_srcdir)/contrib/cex \ -I$(top_srcdir)/contrib/cli11 \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/p2p \ -I$(top_srcdir)/src/tools \ @@ -16,7 +16,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/core -AM_LDFLAGS=-L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto +AM_LDFLAGS=-L$(top_builddir)/$(NODE_PATH)/src -L$(top_builddir)/$(NODE_PATH)/src/crypto L15_LIBS = \ $(top_builddir)/src/api/libl15-api.la \ @@ -24,16 +24,21 @@ $(top_builddir)/src/core/libl15-core.la \ $(top_builddir)/src/tools/libl15-tools.la \ $(top_builddir)/src/common/libl15-common.la \ -lbitcoin_common -lbitcoin_util -lbitcoin_consensus \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_base.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_avx2.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_x86_shani.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_sse41.la \ -$(top_builddir)/contrib/secp256k1/libsecp256k1.la \ -$(top_builddir)/node/src/libunivalue.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_base.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_avx2.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_x86_shani.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_sse41.la \ +$(top_builddir)/$(NODE_PATH)/src/libunivalue.la \ +$(top_builddir)/$(SECP256K1_PATH)/libsecp256k1.la \ $(BOOST_FILESYSTEM_LIB) -bin_PROGRAMS = test_p2p_frost +bin_PROGRAMS = +if BUILD_FROST + + bin_PROGRAMS += test_p2p_frost + test_p2p_frost_SOURCES = test_p2p_frost.cpp + test_p2p_frost_LDADD = $(L15_LIBS) + +endif -test_p2p_frost_SOURCES = test_p2p_frost.cpp -test_p2p_frost_LDADD = $(L15_LIBS) diff --git a/test/python_module/exception_test.py b/test/python_module/exception_test.py deleted file mode 100644 index 110c7b6..0000000 --- a/test/python_module/exception_test.py +++ /dev/null @@ -1,32 +0,0 @@ -import unittest -import sys -from binascii import hexlify - -sys.path.append("../build/src/python_binding") - -import libl15_core_pybind as l15 - -class ExceptionsTestCase(unittest.TestCase): - def test_call_plugin_function(self): - try: - str = l15.Version() - self.assertFalse(str == "") - except: - self.fail("Library cannot be loaded") - - def test_std_exception(self): - networkMode = "wrongNetwork" - with self.assertRaisesRegex(Exception, "wrong chain mode: " + networkMode): - l15.CreateInscriptionBuilder(networkMode) - - def test_l15_exception(self): - with self.assertRaisesRegex(Exception, "No destination public key is provided"): - builder = l15.CreateInscriptionBuilder("regtest") - - builder.UTXO("abcdefgh", 1, "1").\ - Data("text", hexlify("content".encode()).decode()).\ - FeeRate("0.00005").\ - Sign("34234234") - -if __name__ == '__main__': - unittest.main() diff --git a/test/service/Makefile.am b/test/service/Makefile.am index c8ab012..6ac3d48 100644 --- a/test/service/Makefile.am +++ b/test/service/Makefile.am @@ -4,12 +4,12 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/contrib \ -I$(top_srcdir)/contrib/cex \ -I$(top_srcdir)/contrib/cli11 \ - -I$(top_srcdir)/contrib/secp256k1/include \ - -I$(top_srcdir)/node/src \ - -I$(top_srcdir)/node/src/univalue/include \ - -I$(top_srcdir)/node/src/consensus \ - -I$(top_srcdir)/node/src/script \ - -I$(top_srcdir)/node/src/support \ + -I$(top_srcdir)/$(SECP256K1_PATH)/include \ + -I$(top_srcdir)/$(NODE_PATH)/src \ + -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/script \ + -I$(top_srcdir)/$(NODE_PATH)/src/support \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/src/p2p \ -I$(top_srcdir)/src/tools \ @@ -18,7 +18,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/service -AM_LDFLAGS=-L$(top_builddir)/node/src -L$(top_builddir)/node/src/crypto +AM_LDFLAGS=-L$(top_builddir)/$(NODE_PATH)/src -L$(top_builddir)/$(NODE_PATH)/src/crypto L15_LIBS = \ $(top_builddir)/src/service/libl15-srv.la \ @@ -27,16 +27,24 @@ $(top_builddir)/src/core/libl15-core.la \ $(top_builddir)/src/tools/libl15-tools.la \ $(top_builddir)/src/common/libl15-common.la \ -lbitcoin_common -lbitcoin_util -lbitcoin_consensus \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_base.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_avx2.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_x86_shani.la \ -$(top_builddir)/node/src/crypto/libbitcoin_crypto_sse41.la \ -$(top_builddir)/contrib/secp256k1/libsecp256k1.la \ -$(top_builddir)/node/src/libunivalue.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_base.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_avx2.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_x86_shani.la \ +$(top_builddir)/$(NODE_PATH)/src/crypto/libbitcoin_crypto_sse41.la \ +$(top_builddir)/$(NODE_PATH)/src/libunivalue.la \ +$(top_builddir)/$(SECP256K1_PATH)/libsecp256k1.la \ $(BOOST_FILESYSTEM_LIB) -bin_PROGRAMS = test_onchain_service test_generic_service test_signer_service +bin_PROGRAMS = test_onchain_service test_generic_service +if BUILD_FROST + + bin_PROGRAMS += test_signer_service + + test_signer_service_SOURCES = test_signer_service.cpp + test_signer_service_LDADD = $(L15_LIBS) + +endif test_onchain_service_CPPFLAGS = $(AM_CPPFLAGS) $(ZMQ_CPPFLAGS) test_onchain_service_SOURCES = test_onchain_service.cpp @@ -45,5 +53,3 @@ test_onchain_service_LDADD = $(ZMQ_LDFLAGS) $(L15_LIBS) $(ZMQ_LIBS) test_generic_service_SOURCES = test_generic_service.cpp test_generic_service_LDADD = $(L15_LIBS) -test_signer_service_SOURCES = test_signer_service.cpp -test_signer_service_LDADD = $(L15_LIBS) diff --git a/test/test_case_wrapper.hpp b/test/test_case_wrapper.hpp index a271315..9905b6d 100644 --- a/test/test_case_wrapper.hpp +++ b/test/test_case_wrapper.hpp @@ -35,11 +35,11 @@ struct TestcaseWrapper ExecHelper mBtcd; std::unique_ptr mBech; - explicit TestcaseWrapper(const std::string& configpath) : + explicit TestcaseWrapper(const std::string& configpath, const std::string& clipath) : mConfFactory(configpath), mMode(mConfFactory.conf[config::option::CHAINMODE].as()), - mBtc(std::move(mConfFactory.conf.ChainValues(config::BITCOIN)), "l15node-cli"), - mCli("l15node-cli", false), + mBtc(std::move(mConfFactory.conf.ChainValues(config::BITCOIN)), clipath), + mCli(clipath, false), mBtcd("bitcoind", false) { if (mMode == "regtest") { @@ -104,6 +104,15 @@ struct TestcaseWrapper IBech32Coder& bech32() const { return *mBech; } + + void ResetRegtestMemPool() + { + StartRegtestBitcoinNode(); + + std::filesystem::remove(mConfFactory.GetBitcoinDataDir() + "/regtest/mempool.dat"); + + StopRegtestBitcoinNode(); + } }; } \ No newline at end of file From f13cc049d4d727c5faf28204f2b888b8f71a72e7 Mon Sep 17 00:00:00 2001 From: l2xl Date: Mon, 19 Jun 2023 21:46:53 +0300 Subject: [PATCH 02/59] Reconfigure build for UTXORD --- configure.ac | 73 ++++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/configure.ac b/configure.ac index 1fd99b8..fca2658 100644 --- a/configure.ac +++ b/configure.ac @@ -34,13 +34,6 @@ else LDFLAGS_overridden= fi -compiler_name=`basename "$CC"` -if test "x$compiler_name" = "xemcc"; then - with_emscripten=yes -else - with_emscripten=no -fi - # Checks for programs. AC_PROG_CC AC_PROG_CXX @@ -49,6 +42,7 @@ AC_PROG_MKDIR_P AX_CXX_COMPILE_STDCXX([20], [noext], [mandatory]) + default_build_tools=yes default_build_services=yes default_build_apis=yes @@ -58,26 +52,33 @@ default_blockchain_node=node default_secp256k1=contrib/secp256k1 dnl Enable Python integrations -AC_ARG_ENABLE([python-binding], - [AS_HELP_STRING([--enable-python-binding],[Enable API binding module for python (disabled by default)])], - [ - if test $enableval != no; then - default_plugin_api=yes - fi - ], - [enable_python_binding=no]) - -AC_ARG_ENABLE([wasm-module], - [AS_HELP_STRING([--enable-wasm-module], [Enable plugin API binding for WebAssembly (disabled by default)])], - [ - if test $enableval != no; then - default_plugin_api=yes - fi - ], - [enable_wasm_module=no]) +dnl AC_ARG_ENABLE([python-binding], +dnl [AS_HELP_STRING([--enable-python-binding], [Enable plugin API binding module for python (disabled by default)])], +dnl [ +dnl if test $enableval != no; then +dnl default_plugin_api=yes +dnl fi +dnl ], +dnl [enable_python_binding=no]) +dnl +dnl AC_ARG_ENABLE([wasm-binding], +dnl [AS_HELP_STRING([--enable-wasm-binding], [Enable plugin API binding for WebAssembly (disabled by default)])], +dnl [ +dnl if test $enableval != no; then +dnl default_plugin_api=yes +dnl fi +dnl ], +dnl [enable_wasm_binding=no]) +dnl +dnl if test "$enable_python_binding" = "yes" && test "$enable_wasm_binding" = "yes"; then +dnl AC_MSG_ERROR([WebAssembly and Python bindings cannot be built simultaneously]) +dnl fi -if test "$enable_python_module" = "yes" && "$enable_wasm_module" = "yes"; then - AC_MSG_ERROR([WebAssembly and Python modules cannot be build simultaneously]) +compiler_name=`basename "$CC"` +if test "x$compiler_name" = "xemcc"; then + with_emscripten=yes +else + with_emscripten=no fi AC_ARG_ENABLE([plugin-api], @@ -170,8 +171,8 @@ AM_CONDITIONAL([BUILD_APIS], [test "$enable_build_apis" = "yes"]) AM_CONDITIONAL([BUILD_SERVICES], [test "$enable_build_services" = "yes"]) AM_CONDITIONAL([BUILD_TOOLS], [test "$enable_build_tools" = "yes"]) AM_CONDITIONAL([BUILD_PLUGIN_API], [test "$enable_plugin_api" = "yes"]) -AM_CONDITIONAL([BUILD_PYTHON_MODULE], [test "$enable_python_module" = "yes"]) -AM_CONDITIONAL([BUILD_WASM_MODULE], [test "$enable_wasm_module" = "yes"]) +#AM_CONDITIONAL([BUILD_PYTHON_MODULE], [test "$enable_python_module" = "yes"]) +#AM_CONDITIONAL([BUILD_WASM_MODULE], [test "$enable_wasm_module" = "yes"]) AM_CONDITIONAL([BUILD_SECP256K1], [test "$with_secp256k1" != "node"]) AM_CONDITIONAL([BUILD_FROST], [test "$enable_build_frost_signer" = "yes"]) @@ -197,7 +198,15 @@ if test "$LDLAGS_overridden" != "yes"; then fi -if test "$enable_debug" = "yes"; then +if test "x$enable_build_apis" = "xyes"; then + AX_BOOST_BASE([1.70]) + AX_BOOST_FILESYSTEM +fi + +AC_LANG_PUSH([C++]) +AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAG_WERROR="-Werror"]) + +if test "x$enable_debug" = "xyes"; then dnl Disable all optimizations AX_CHECK_COMPILE_FLAG([-O0], [DEBUG_CXXFLAGS="$DEBUG_CXXFLAGS -O0"], [], [$CXXFLAG_WERROR]) @@ -214,11 +223,7 @@ if test "$enable_debug" = "yes"; then fi -# Checks for libraries. -AX_BOOST_BASE([1.70],, [AC_MSG_ERROR([Boost 1.70 or higher is needed, but it was not found in your system])]) -AX_BOOST_FILESYSTEM(,[AC_MSG_ERROR([libboost_filesystem is required, but it was not found in your system])]) - -if test "$enable_wasm_module" = "yes"; then +if test "$enable_wasm_binding" = "yes"; then CPPFLAGS="$DEBUG_CPPFLAGS $CPPFLAGS" CXXFLAGS="$DEBUG_CXXFLAGS $CXXFLAGS -fexceptions -Wno-unqualified-std-cast-call" LDFLAGS="$LDFLAGS -fexceptions -sEXPORT_EXCEPTION_HANDLING_HELPERS -sLLD_REPORT_UNDEFINED -sEXPORTED_FUNCTIONS=['_malloc'] -sEXPORT_NAME='L15' -sMODULARIZE=1 -sNO_FILESYSTEM=1" From cb60a3026cf54945ec0e76781d74f3d20e6f693b Mon Sep 17 00:00:00 2001 From: l2xl Date: Thu, 22 Jun 2023 23:34:38 +0300 Subject: [PATCH 03/59] Improve emscripten build for node --- build-aux/m4/ax_zmq.m4 | 3 ++- configure.ac | 31 ++++++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/build-aux/m4/ax_zmq.m4 b/build-aux/m4/ax_zmq.m4 index f51f272..b67b4c1 100644 --- a/build-aux/m4/ax_zmq.m4 +++ b/build-aux/m4/ax_zmq.m4 @@ -44,7 +44,8 @@ AC_DEFUN([AX_ZMQ], [ [xyes],[with_zmq=yes], [xno],[with_zmq=no], [with_zmq=yes; ZMQ_LDFLAGS="-L${withval}/lib"; ZMQ_CPPFLAGS="-I${withval}/include"] - )]) + )], + [with_zmq=yes]) HAVE_ZMQ=0 if test "$with_zmq" != "no"; then diff --git a/configure.ac b/configure.ac index fca2658..02d2aab 100644 --- a/configure.ac +++ b/configure.ac @@ -337,12 +337,19 @@ AS_IF([test "$enable_plugin_api" = "yes"], [btc_utils=--without-utils], AS_IF([test "$enable_plugin_api" = "yes"], [btc_daemon=--without-daemon], [btc_daemon=--with-daemon]) +AS_IF([test "$enable_plugin_api" = "yes"], [limited_api=--enable-limited-api], + [limited_api="--enable-limited-api=no"]) + AS_IF([test "$with_emscripten" = "yes"], [btc_asm=--disable-asm], [btc_asm=--enable-asm]) +AS_IF([test "$with_emscripten" = "yes"], [btc_hardening=--disable-hardening], + [btc_hardening=--enable-hardening]) + AS_IF([test "x$with_zmq" = "xyes"], [btc_zmq=--with-zmq], - [test "x$with_zmq" != "xno"], [btc_zmq="--with-zmq=$with_zmq"], - [btc_zmq=--without-zmq]) + [test "x$with_zmq" = "xno"], [btc_zmq="--without-zmq"], + [test -z "$with_zmq"], [btc_zmq="--without-zmq"], + [btc_zmq="--with-zmq=$with_zmq"]) AX_SUBDIRS_CONFIGURE( @@ -351,15 +358,29 @@ AX_SUBDIRS_CONFIGURE( [--with-libs], [--without-bdb], [$btc_sqlite], [$btc_zmq], [--without-libmultiprocess], [--without-mpgen], [$btc_utils], [$btc_cli], [$btc_daemon], - [--with-experimental-kernel-lib],[--disable-experimental-util-chainstate], + [--without-experimental-kernel-lib],[--disable-experimental-util-chainstate], [--disable-multiprocess], [--disable-external-signer], [--disable-usdt], + [$btc_hardening], [--disable-tests], [--disable-gui-tests], [--disable-bench], [--disable-extended-functional-tests], [--disable-fuzz], [--disable-fuzz-binary], - [$btc_asm]], + [$btc_asm], + [$limited_api]], [[--disable-tests], [--disable-bench], [--with-pic]], [[--disable-examples]], - [[--with-blockchain-node], [--with-secp256k1], [--enable-build-tools], [--enable-build-services], [--enable-build-apis]]) + [[--with-blockchain-node=$with_blockchain_node], + [--enable-wasm-binding], + [--enable-python-binding], + [--with-secp256k1=$with_secp256k1], + [--disable-build-tools], + [--disable-build-services], + [--disable-build-apis], + [--disable-build-frost-signer], + [--disable-build-tools], + [--disable-build-services], + [--disable-build-apis], + [--enable-plugin-api], + [--disable-plugin-api]]) if test "$with_secp256k1" != "node"; then AX_SUBDIRS_CONFIGURE( From 02c659e9b8d57ed989b67b6228c21bce6691d69b Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 28 Jun 2023 01:23:22 +0300 Subject: [PATCH 04/59] Make hex()/unhex() template args more flexible --- src/common/common.hpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/common/common.hpp b/src/common/common.hpp index bba88a1..531eb7e 100644 --- a/src/common/common.hpp +++ b/src/common/common.hpp @@ -138,6 +138,24 @@ std::string hex(const SPAN& s) return res; } +template +requires (std::is_same_v) +std::string hex(const T& s) +{ + std::string res(s.size() * 2, '\0'); + + char* it = res.data(); + for (std::byte v : s) { + *it = byte_to_hex[static_cast(v)][0]; + ++it; + *it = byte_to_hex[static_cast(v)][1]; + ++it; + } + + assert(it == res.data() + res.size()); + return res; +} + template constexpr R unhex(std::string_view str) { if (str.length()%2) { @@ -157,6 +175,26 @@ constexpr R unhex(std::string_view str) { return res; } +template +requires (std::is_same_v) +constexpr R unhex(std::string_view str) { + if (str.length()%2) { + throw std::out_of_range("Wrong hex string length"); + } + + R res; + res.resize(str.length() / 2); + + auto ins = res.begin(); + for (auto i = str.begin(); i != str.end(); i+=2) { + auto& p = reinterpret_cast(*ins++); + auto conv_res = std::from_chars(i, i+2, p, 16); + if (conv_res.ec == std::errc::invalid_argument) { + throw std::invalid_argument("Wrong hex string"); + } + } + return res; +} template static bool IsZeroArray(const T& a) From 454f45f0690fd675fa73b11f18730f61f51d585e Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 28 Jun 2023 21:49:07 +0300 Subject: [PATCH 05/59] MasterKey class for BIP32 and descedants key derivations --- src/core/Makefile.am | 2 + src/core/channel_keys.cpp | 44 ++++++++------- src/core/channel_keys.hpp | 6 +- src/core/master_key.cpp | 102 ++++++++++++++++++++++++++++++++++ src/core/master_key.hpp | 50 +++++++++++++++++ test/core/Makefile.am | 5 +- test/core/test_derive_key.cpp | 52 +++++++++++++++++ test/core/test_taproot.cpp | 4 +- test/core/test_taptree.cpp | 11 ++-- 9 files changed, 244 insertions(+), 32 deletions(-) create mode 100644 src/core/master_key.cpp create mode 100644 src/core/master_key.hpp create mode 100644 test/core/test_derive_key.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index edcd6a2..4bd6f2b 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -6,6 +6,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/$(NODE_PATH)/src/primitives \ -I$(top_srcdir)/$(NODE_PATH)/src/script \ -I$(top_srcdir)/$(NODE_PATH)/src/support \ + -I$(top_srcdir)/$(NODE_PATH)/src/crypto \ -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/src/common \ -I$(top_srcdir)/contrib/cex @@ -15,6 +16,7 @@ noinst_LTLIBRARIES = libl15-core.la libl15_core_la_SOURCES = \ script_merkle_tree.cpp \ channel_keys.cpp \ + master_key.cpp \ transaction.cpp # channel_contract.cpp diff --git a/src/core/channel_keys.cpp b/src/core/channel_keys.cpp index bef7f60..d2ea922 100644 --- a/src/core/channel_keys.cpp +++ b/src/core/channel_keys.cpp @@ -112,40 +112,43 @@ void ChannelKeys::CachePubkey() //} -std::pair ChannelKeys::AddTapTweak(const uint256& merkle_root) const +std::pair ChannelKeys::AddTapTweak(const std::optional& merkle_root) { - secp256k1_pubkey out; - HashWriter hash(TAPTWEAK_HASH); hash << Span(GetPubKey()); - hash << merkle_root; - + if (merkle_root.has_value()) { + hash << *merkle_root; + } uint256 tweak = hash; - secp256k1_xonly_pubkey pubkey_agg = m_pubkey_agg.get(m_ctx); + secp256k1_keypair keypair; + if (!secp256k1_keypair_create(Secp256k1Context(), &keypair, m_local_sk.data())) { + throw WrongKeyError(); + } - if (!secp256k1_xonly_pubkey_tweak_add(m_ctx, &out, &pubkey_agg, tweak.data())) { + if (!secp256k1_keypair_xonly_tweak_add(Secp256k1Context(), &keypair, tweak.data())) { throw SignatureError("Tweak error"); } - int parity = -1; - std::pair ret; - secp256k1_xonly_pubkey out_xonly; - - if (!secp256k1_xonly_pubkey_from_pubkey(m_ctx, &out_xonly, &parity, &out)) { + seckey tweaked_sk; + if (!secp256k1_keypair_sec(Secp256k1Context(), tweaked_sk.data(), &keypair)) { throw KeyError(); } - ret.first.set(m_ctx, out_xonly); - - assert(parity == 0 || parity == 1); + secp256k1_xonly_pubkey tweaked_pk; + int parity = -1; + if (!secp256k1_keypair_xonly_pub(Secp256k1Context(), &tweaked_pk, &parity, &keypair)) { + throw KeyError(); + } - ret.second = parity; + m_local_sk = move(tweaked_sk); + m_local_pk.set(m_ctx, tweaked_pk); + m_pubkey_agg = m_local_pk; - return ret; + return std::make_pair(GetPubKey(), static_cast(parity)); } -std::pair ChannelKeys::NewKeyAddTapTweak(std::optional merkle_root) const +std::pair ChannelKeys::NewKeyAddTapTweak(const std::optional& merkle_root) const { HashWriter hash(TAPTWEAK_HASH); hash << Span(GetPubKey()); @@ -206,7 +209,7 @@ xonly_pubkey ChannelKeys::CreateUnspendablePubKey(const seckey &random_factor) } -std::pair ChannelKeys::AddTapTweak(const xonly_pubkey &pk, const uint256& merkle_root) +std::pair ChannelKeys::AddTapTweak(const xonly_pubkey &pk, const std::optional& merkle_root) { const secp256k1_context* ctx = GetStaticSecp256k1Context(); @@ -214,7 +217,8 @@ std::pair ChannelKeys::AddTapTweak(const xonly_pubkey &pk HashWriter hash(TAPTWEAK_HASH); hash << Span(pk); - hash << merkle_root; + if (merkle_root.has_value()) + hash << *merkle_root; uint256 tweak = hash; secp256k1_xonly_pubkey pubkey = pk.get(ctx); diff --git a/src/core/channel_keys.hpp b/src/core/channel_keys.hpp index 25ae475..18d2084 100644 --- a/src/core/channel_keys.hpp +++ b/src/core/channel_keys.hpp @@ -66,10 +66,10 @@ class ChannelKeys static seckey GetStrongRandomKey(const secp256k1_context* ctx = GetStaticSecp256k1Context()) ; static xonly_pubkey CreateUnspendablePubKey(const seckey& random_factor); - static std::pair AddTapTweak(const xonly_pubkey& pk, const uint256& merkle_root); - std::pair AddTapTweak(const uint256& merkle_root) const; + static std::pair AddTapTweak(const xonly_pubkey& pk, const std::optional& merkle_root = {}); + std::pair AddTapTweak(const std::optional& merkle_root = {}); - std::pair NewKeyAddTapTweak(std::optional merkle_root) const; + std::pair NewKeyAddTapTweak(const std::optional& merkle_root = {}) const; signature SignSchnorr(const uint256& data) const; diff --git a/src/core/master_key.cpp b/src/core/master_key.cpp new file mode 100644 index 0000000..e006281 --- /dev/null +++ b/src/core/master_key.cpp @@ -0,0 +1,102 @@ +#include "master_key.hpp" +#include "util/spanparsing.h" +#include "hmac_sha512.h" + +namespace l15::core { + +namespace { + const unsigned char seed_hash_tag[] = {'B', 'i', 't', 'c', 'o', 'i', 'n', ' ', 's', 'e', 'e', 'd'}; +} + +MasterKey::MasterKey(const secp256k1_context* ctx, const std::vector& seed) : m_ctx(ctx) +{ + std::vector> vout(64); + CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data()); + mKey.assign(vout.data(), vout.data() + 32); + memcpy(mChainCode.begin(), vout.data() + 32, 32); +} + +MasterKey::MasterKey(const std::vector& seed) : m_ctx(ChannelKeys::GetStaticSecp256k1Context()) +{ + std::vector> vout(64); + CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data()); + mKey.assign(vout.data(), vout.data() + 32); + memcpy(mChainCode.begin(), vout.data() + 32, 32); +} + +void MasterKey::DeriveSelf(uint32_t branch) +{ + std::vector> vout(64); + if ((branch >> 31) == 0) { + + secp256k1_pubkey pubkey; + + if (!secp256k1_ec_pubkey_create(m_ctx, &pubkey, mKey.data())) { + throw KeyError(); + } + size_t pubkeylen = 33; + bytevector pubkeydata(pubkeylen); + if (!secp256k1_ec_pubkey_serialize(m_ctx, pubkeydata.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { + throw KeyError(); + } + BIP32Hash(mChainCode, branch, *pubkeydata.begin(), pubkeydata.data()+1, vout.data()); + } else { + BIP32Hash(mChainCode, branch, 0, mKey.data(), vout.data()); + } + + memcpy(mChainCode.begin(), vout.data()+32, 32); + + if (!secp256k1_ec_seckey_tweak_add(m_ctx, mKey.data(), vout.data())) { + throw KeyError(); + } +} + +ChannelKeys MasterKey::MakeKey(bool do_tweak) +{ + ChannelKeys res(m_ctx, mKey); + + if (do_tweak) { + res.AddTapTweak(); + } + + return res; +} + +ChannelKeys MasterKey::Derive(const string &path, bool for_script) const +{ + auto branches = spanparsing::Split(path, '/'); + + BIP86Tweak do_tweak = for_script ? SUPPRESS : AUTO; + + if (branches.front()[0] != 'm' || branches.front().size() != 1) { + throw KeyError(); + } + branches.erase(branches.begin()); + + std::vector uint_branches; + uint_branches.reserve(branches.size()); + + for (const auto& branch: branches) { + uint32_t index; + if (branch[branch.size() - 1] == '\'') { + //hardened + auto conv_res = std::from_chars(branch.begin(), branch.end() - 1, index); + if (conv_res.ec == std::errc::invalid_argument) { + throw std::invalid_argument("Wrong hex string"); + } + index += BIP32_HARDENED_KEY_LIMIT; + } + else { + // non hardened + auto conv_res = std::from_chars(branch.begin(), branch.end(), index); + if (conv_res.ec == std::errc::invalid_argument) { + throw std::invalid_argument("Wrong hex string"); + } + } + uint_branches.push_back(index); + } + return Derive(uint_branches, do_tweak); +} + + +} // l15::core \ No newline at end of file diff --git a/src/core/master_key.hpp b/src/core/master_key.hpp new file mode 100644 index 0000000..dfe0927 --- /dev/null +++ b/src/core/master_key.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "channel_keys.hpp" + +namespace l15::core { + +enum BIP86Tweak {AUTO, FORCE, SUPPRESS}; + +class MasterKey +{ +public: + static const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; + static const uint32_t BIP32_BRANCH_MASK = 0x7fffffff; + static const uint32_t BIP86_TAPROOT_ACCOUNT = 86; +private: + const secp256k1_context* m_ctx; + seckey mKey; + uint256 mChainCode; + + explicit MasterKey(const secp256k1_context* ctx) : m_ctx(ctx) {} + +public: + MasterKey(const secp256k1_context* ctx, const std::vector& seed); + explicit MasterKey(const std::vector& seed); + + MasterKey(const MasterKey&) = default; + MasterKey(MasterKey&& ) = default; + + ChannelKeys MakeKey(bool do_tweak); + + void DeriveSelf(uint32_t branch); + + template + ChannelKeys Derive(const T& branches, BIP86Tweak bip86_tweak) const + { + MasterKey branchKey(*this); + + for (const auto& b: branches) { + branchKey.DeriveSelf(b); + } + + bool do_tweak = (bip86_tweak == FORCE) || (bip86_tweak == AUTO && (branches.front() & BIP32_BRANCH_MASK) == BIP86_TAPROOT_ACCOUNT); + return branchKey.MakeKey(do_tweak); + } + + ChannelKeys Derive(const std::string& path, bool for_script = false) const; +}; + +} // l15::core + diff --git a/test/core/Makefile.am b/test/core/Makefile.am index 7d45def..cf1fc64 100644 --- a/test/core/Makefile.am +++ b/test/core/Makefile.am @@ -33,7 +33,7 @@ $(top_builddir)/$(NODE_PATH)/src/libunivalue.la \ $(top_builddir)/$(SECP256K1_PATH)/libsecp256k1.la \ $(BOOST_FILESYSTEM_LIB) -bin_PROGRAMS = test_taptree test_taproot test_node +bin_PROGRAMS = test_taptree test_taproot test_node test_derive_key #test_ptlc if BUILD_FROST @@ -61,3 +61,6 @@ test_node_SOURCES = test_node.cpp test_node_LDADD = $(L15_LIBS) +test_derive_key_SOURCES = test_derive_key.cpp +test_derive_key_LDADD = $(L15_LIBS) + diff --git a/test/core/test_derive_key.cpp b/test/core/test_derive_key.cpp new file mode 100644 index 0000000..16e82f0 --- /dev/null +++ b/test/core/test_derive_key.cpp @@ -0,0 +1,52 @@ +#include +#include +#include + +#define CATCH_CONFIG_MAIN +#include "catch/catch.hpp" + +#include "util/translation.h" +#include "master_key.hpp" +#include "utils.hpp" + +using namespace l15; +using namespace l15::core; + +const std::function G_TRANSLATION_FUN = nullptr; + +static const std::vector seed = unhex>( + "b37f263befa23efb352f0ba45a5e452363963fabc64c946a75df155244630ebaa1ac8056b873e79232486d5dd36809f8925c9c5ac8322f5380940badc64cc6fe"); + +static const auto bech = Bech32Coder(); + +static const std::vector derive_branches = { + MasterKey::BIP86_TAPROOT_ACCOUNT | MasterKey::BIP32_HARDENED_KEY_LIMIT, + 2 | MasterKey::BIP32_HARDENED_KEY_LIMIT, + MasterKey::BIP32_HARDENED_KEY_LIMIT, + 0, 0}; + +static const std::string derive_path = "m/86'/2'/0'/0/0"; + +TEST_CASE("Seed") +{ + MasterKey extkey(seed); + REQUIRE(bech.Encode(extkey.MakeKey(false).GetLocalPubKey()) == "tb1pz6zkdhjmar4x243yve469lex9htp8j2qzcu79s7mm420hddmwxssmngtnz"); +} + +TEST_CASE("Derive") +{ + MasterKey master(seed); + + ChannelKeys derived = master.Derive(derive_branches, AUTO); + + REQUIRE(bech.Encode(derived.GetLocalPubKey()) == "tb1ptnn4tufj4yr8ql0e8w8tye7juxzsndnxgnlehfk2p0skftzks20sncm2dz"); +} + +TEST_CASE("DerivePath") +{ + MasterKey master(seed); + + ChannelKeys derived = master.Derive(derive_path, false); + + REQUIRE(bech.Encode(derived.GetLocalPubKey()) == "tb1ptnn4tufj4yr8ql0e8w8tye7juxzsndnxgnlehfk2p0skftzks20sncm2dz"); +} diff --git a/test/core/test_taproot.cpp b/test/core/test_taproot.cpp index 82110ef..d78629b 100644 --- a/test/core/test_taproot.cpp +++ b/test/core/test_taproot.cpp @@ -118,7 +118,7 @@ TEST_CASE("Taproot transaction test cases") { //get key pair Taproot ChannelKeys internal_sk; - const auto& internal_pk = internal_sk.GetLocalPubKey(); + xonly_pubkey internal_pk = internal_sk.GetLocalPubKey(); std::clog << "\nInternal PK: " << HexStr(internal_pk) << std::endl; @@ -143,7 +143,7 @@ TEST_CASE("Taproot transaction test cases") xonly_pubkey taprootpubkey; uint8_t taprootpubkeyparity; - std::tie(taprootpubkey, taprootpubkeyparity) = internal_sk.AddTapTweak(root); + std::tie(taprootpubkey, taprootpubkeyparity) = internal_sk.AddTapTweak(std::make_optional(root)); string addr = w->bech32().Encode(taprootpubkey); std::clog << "\nTaproot PK: " << HexStr(taprootpubkey) << std::endl; diff --git a/test/core/test_taptree.cpp b/test/core/test_taptree.cpp index 865263b..cebdd5b 100644 --- a/test/core/test_taptree.cpp +++ b/test/core/test_taptree.cpp @@ -68,19 +68,18 @@ TEST_CASE("TapTweak") WalletApi wallet; ChannelKeys key(wallet.Secp256k1Context()); + XOnlyPubKey pk(key.GetPubKey()); // Lets just simulate some uint256 l15::HashWriter hash(TAPBRANCH_HASH); hash << "test test test"; uint256 fake_root = hash; - auto taprootkey = key.AddTapTweak(fake_root); - + auto taprootkey = key.AddTapTweak(std::make_optional(fake_root)); XOnlyPubKey xonlypubkey(taprootkey.first); - CHECK(xonlypubkey.CheckTapTweak(XOnlyPubKey(key.GetPubKey()), fake_root, taprootkey.second)); - + CHECK(xonlypubkey.CheckTapTweak(pk, fake_root, taprootkey.second)); } TEST_CASE("TapRoot single script") @@ -89,7 +88,7 @@ TEST_CASE("TapRoot single script") //get key pair Taproot auto internal_sk = ChannelKeys(wallet.Secp256k1Context()); - const auto& internal_pk = internal_sk.GetLocalPubKey(); + xonly_pubkey internal_pk = internal_sk.GetLocalPubKey(); std::clog << "Internal PK: " << HexStr(internal_pk) << std::endl; @@ -108,7 +107,7 @@ TEST_CASE("TapRoot single script") ScriptMerkleTree tap_tree (TreeBalanceType::WEIGHTED, {script}); uint256 root = tap_tree.CalculateRoot(); - auto tap_root = internal_sk.AddTapTweak(root); + auto tap_root = internal_sk.AddTapTweak(std::make_optional(root)); XOnlyPubKey xonly_internal_pubkey(internal_pk); From ca63d97d2e8671775fbd10a3b6e907c956c89c0b Mon Sep 17 00:00:00 2001 From: l2xl Date: Mon, 3 Jul 2023 23:44:45 +0300 Subject: [PATCH 06/59] WASM related MasterKey fixes --- configure.ac | 24 ----------- src/common/common_error.hpp | 2 + src/core/channel_keys.cpp | 77 +++++++++++++++++++++-------------- src/core/master_key.cpp | 63 ++++++++++++++++------------ src/core/master_key.hpp | 4 +- test/core/test_derive_key.cpp | 2 +- 6 files changed, 87 insertions(+), 85 deletions(-) diff --git a/configure.ac b/configure.ac index 02d2aab..cd2ae2f 100644 --- a/configure.ac +++ b/configure.ac @@ -51,28 +51,6 @@ default_plugin_api=no default_blockchain_node=node default_secp256k1=contrib/secp256k1 -dnl Enable Python integrations -dnl AC_ARG_ENABLE([python-binding], -dnl [AS_HELP_STRING([--enable-python-binding], [Enable plugin API binding module for python (disabled by default)])], -dnl [ -dnl if test $enableval != no; then -dnl default_plugin_api=yes -dnl fi -dnl ], -dnl [enable_python_binding=no]) -dnl -dnl AC_ARG_ENABLE([wasm-binding], -dnl [AS_HELP_STRING([--enable-wasm-binding], [Enable plugin API binding for WebAssembly (disabled by default)])], -dnl [ -dnl if test $enableval != no; then -dnl default_plugin_api=yes -dnl fi -dnl ], -dnl [enable_wasm_binding=no]) -dnl -dnl if test "$enable_python_binding" = "yes" && test "$enable_wasm_binding" = "yes"; then -dnl AC_MSG_ERROR([WebAssembly and Python bindings cannot be built simultaneously]) -dnl fi compiler_name=`basename "$CC"` if test "x$compiler_name" = "xemcc"; then @@ -171,8 +149,6 @@ AM_CONDITIONAL([BUILD_APIS], [test "$enable_build_apis" = "yes"]) AM_CONDITIONAL([BUILD_SERVICES], [test "$enable_build_services" = "yes"]) AM_CONDITIONAL([BUILD_TOOLS], [test "$enable_build_tools" = "yes"]) AM_CONDITIONAL([BUILD_PLUGIN_API], [test "$enable_plugin_api" = "yes"]) -#AM_CONDITIONAL([BUILD_PYTHON_MODULE], [test "$enable_python_module" = "yes"]) -#AM_CONDITIONAL([BUILD_WASM_MODULE], [test "$enable_wasm_module" = "yes"]) AM_CONDITIONAL([BUILD_SECP256K1], [test "$with_secp256k1" != "node"]) AM_CONDITIONAL([BUILD_FROST], [test "$enable_build_frost_signer" = "yes"]) diff --git a/src/common/common_error.hpp b/src/common/common_error.hpp index b7fc01b..4201a83 100644 --- a/src/common/common_error.hpp +++ b/src/common/common_error.hpp @@ -17,6 +17,8 @@ class Error : public std::exception { class KeyError : public Error { public: + KeyError() = default; + explicit KeyError(std::string&& details) : Error(move(details)) {} ~KeyError() override = default; const char* what() const noexcept override diff --git a/src/core/channel_keys.cpp b/src/core/channel_keys.cpp index d2ea922..cbf7a4e 100644 --- a/src/core/channel_keys.cpp +++ b/src/core/channel_keys.cpp @@ -121,24 +121,33 @@ std::pair ChannelKeys::AddTapTweak(const std::optional ChannelKeys::NewKeyAddTapTweak(const std::option } uint256 tweak = hash; + seckey tweaked_sk; + secp256k1_xonly_pubkey tweaked_pk; secp256k1_keypair keypair; - if (!secp256k1_keypair_create(Secp256k1Context(), &keypair, m_local_sk.data())) { - throw WrongKeyError(); - } - - if (!secp256k1_keypair_xonly_tweak_add(Secp256k1Context(), &keypair, tweak.data())) { - throw SignatureError("Tweak error"); - } + int parity = -1; + try { + if (!secp256k1_keypair_create(Secp256k1Context(), &keypair, m_local_sk.data())) { + throw WrongKeyError(); + } - seckey tweaked_sk; - if (!secp256k1_keypair_sec(Secp256k1Context(), tweaked_sk.data(), &keypair)) { - throw KeyError(); - } + if (!secp256k1_keypair_xonly_tweak_add(Secp256k1Context(), &keypair, tweak.data())) { + throw SignatureError("Tweak error"); + } - ChannelKeys tweaked_key(move(tweaked_sk)); + if (!secp256k1_keypair_sec(Secp256k1Context(), tweaked_sk.data(), &keypair)) { + throw KeyError(); + } - secp256k1_xonly_pubkey tweaked_pk; - int parity = -1; - if (!secp256k1_keypair_xonly_pub(Secp256k1Context(), &tweaked_pk, &parity, &keypair)) { - throw KeyError(); + if (!secp256k1_keypair_xonly_pub(Secp256k1Context(), &tweaked_pk, &parity, &keypair)) { + throw KeyError(); + } + memory_cleanse(&keypair, sizeof(keypair)); + } + catch (...) { + memory_cleanse(&keypair, sizeof(keypair)); + std::rethrow_exception(std::current_exception()); } + ChannelKeys tweaked_key(move(tweaked_sk)); return std::make_pair(move(tweaked_key), static_cast(parity)); } @@ -251,7 +266,7 @@ signature ChannelKeys::SignSchnorr(const uint256& data) const seckey aux = GetStrongRandomKey(); secp256k1_keypair keypair; - if (!secp256k1_keypair_create(Secp256k1Context(), &keypair, m_local_sk.data())) throw SignatureError("Key error"); + if (!secp256k1_keypair_create(Secp256k1Context(), &keypair, m_local_sk.data())) throw KeyError(); // if (merkle_root) { // secp256k1_xonly_pubkey pubkey; // if (!secp256k1_keypair_xonly_pub(secp256k1_context_sign, &pubkey, nullptr, &keypair)) return false; diff --git a/src/core/master_key.cpp b/src/core/master_key.cpp index e006281..306ce0f 100644 --- a/src/core/master_key.cpp +++ b/src/core/master_key.cpp @@ -8,46 +8,55 @@ namespace { const unsigned char seed_hash_tag[] = {'B', 'i', 't', 'c', 'o', 'i', 'n', ' ', 's', 'e', 'e', 'd'}; } -MasterKey::MasterKey(const secp256k1_context* ctx, const std::vector& seed) : m_ctx(ctx) +MasterKey::MasterKey(const secp256k1_context* ctx, const bytevector& seed) : m_ctx(ctx), mKey(), mChainCode() { - std::vector> vout(64); - CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data()); - mKey.assign(vout.data(), vout.data() + 32); - memcpy(mChainCode.begin(), vout.data() + 32, 32); + uint8_t vout[64]; + CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(seed.data(), seed.size()).Finalize(vout); + mKey.assign(vout, vout + 32); + memcpy(mChainCode.begin(), vout + 32, 32); + memory_cleanse(vout, sizeof(vout)); } -MasterKey::MasterKey(const std::vector& seed) : m_ctx(ChannelKeys::GetStaticSecp256k1Context()) +MasterKey::MasterKey(const bytevector& seed) : m_ctx(ChannelKeys::GetStaticSecp256k1Context()), mKey(), mChainCode() { - std::vector> vout(64); - CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data()); - mKey.assign(vout.data(), vout.data() + 32); - memcpy(mChainCode.begin(), vout.data() + 32, 32); + uint8_t vout[64]; + CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(seed.data(), seed.size()).Finalize(vout); + mKey.assign(vout, vout + 32); + memcpy(mChainCode.begin(), vout + 32, 32); + memory_cleanse(vout, sizeof(vout)); } void MasterKey::DeriveSelf(uint32_t branch) { - std::vector> vout(64); - if ((branch >> 31) == 0) { + uint8_t vout[64]; - secp256k1_pubkey pubkey; + try { + if ((branch >> 31) == 0) { + secp256k1_pubkey pubkey; - if (!secp256k1_ec_pubkey_create(m_ctx, &pubkey, mKey.data())) { - throw KeyError(); + if (!secp256k1_ec_pubkey_create(m_ctx, &pubkey, mKey.data())) { + throw WrongKeyError(); + } + size_t pubkeylen = 33; + bytevector pubkeydata(pubkeylen); + if (!secp256k1_ec_pubkey_serialize(m_ctx, pubkeydata.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { + throw KeyError("Master pubkey "); + } + BIP32Hash(mChainCode, branch, *pubkeydata.begin(), pubkeydata.data() + 1, vout); } - size_t pubkeylen = 33; - bytevector pubkeydata(pubkeylen); - if (!secp256k1_ec_pubkey_serialize(m_ctx, pubkeydata.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { - throw KeyError(); + else { + BIP32Hash(mChainCode, branch, 0, mKey.data(), vout); } - BIP32Hash(mChainCode, branch, *pubkeydata.begin(), pubkeydata.data()+1, vout.data()); - } else { - BIP32Hash(mChainCode, branch, 0, mKey.data(), vout.data()); - } - memcpy(mChainCode.begin(), vout.data()+32, 32); + memcpy(mChainCode.begin(), vout + 32, 32); - if (!secp256k1_ec_seckey_tweak_add(m_ctx, mKey.data(), vout.data())) { - throw KeyError(); + if (!secp256k1_ec_seckey_tweak_add(m_ctx, mKey.data(), vout)) { + throw KeyError("Derive tweak"); + } + } + catch(...) { + memset(vout, 0, sizeof(vout)); + std::rethrow_exception(std::current_exception()); } } @@ -69,7 +78,7 @@ ChannelKeys MasterKey::Derive(const string &path, bool for_script) const BIP86Tweak do_tweak = for_script ? SUPPRESS : AUTO; if (branches.front()[0] != 'm' || branches.front().size() != 1) { - throw KeyError(); + throw KeyError("Derivation path"); } branches.erase(branches.begin()); diff --git a/src/core/master_key.hpp b/src/core/master_key.hpp index dfe0927..2b06626 100644 --- a/src/core/master_key.hpp +++ b/src/core/master_key.hpp @@ -20,8 +20,8 @@ class MasterKey explicit MasterKey(const secp256k1_context* ctx) : m_ctx(ctx) {} public: - MasterKey(const secp256k1_context* ctx, const std::vector& seed); - explicit MasterKey(const std::vector& seed); + MasterKey(const secp256k1_context* ctx, const bytevector& seed); + explicit MasterKey(const bytevector& seed); MasterKey(const MasterKey&) = default; MasterKey(MasterKey&& ) = default; diff --git a/test/core/test_derive_key.cpp b/test/core/test_derive_key.cpp index 16e82f0..68fef96 100644 --- a/test/core/test_derive_key.cpp +++ b/test/core/test_derive_key.cpp @@ -14,7 +14,7 @@ using namespace l15::core; const std::function G_TRANSLATION_FUN = nullptr; -static const std::vector seed = unhex>( +static const bytevector seed = unhex( "b37f263befa23efb352f0ba45a5e452363963fabc64c946a75df155244630ebaa1ac8056b873e79232486d5dd36809f8925c9c5ac8322f5380940badc64cc6fe"); static const auto bech = Bech32Coder(); From 0691bcad70f97cf66134feea2956161a29265842 Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 5 Jul 2023 19:43:15 +0300 Subject: [PATCH 07/59] boilerplate mainnet config --- test/test-node/mainnet/l15.conf | 7 +++++++ test/test_case_wrapper.hpp | 15 +++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 test/test-node/mainnet/l15.conf diff --git a/test/test-node/mainnet/l15.conf b/test/test-node/mainnet/l15.conf new file mode 100644 index 0000000..e68c99f --- /dev/null +++ b/test/test-node/mainnet/l15.conf @@ -0,0 +1,7 @@ +mode=mainnet + +[bitcoin] +rpcconnect=10.11.11.3 +rpcport=18332 +rpcuser= +rpcpassword= diff --git a/test/test_case_wrapper.hpp b/test/test_case_wrapper.hpp index 9905b6d..acc26ea 100644 --- a/test/test_case_wrapper.hpp +++ b/test/test_case_wrapper.hpp @@ -3,6 +3,8 @@ #include "common.hpp" #include "chain_api.hpp" #include "config.hpp" +#include "exechelper.hpp" +#include "nodehelper.hpp" namespace l15 { @@ -48,6 +50,9 @@ struct TestcaseWrapper else if (mMode == "testnet") { mBech.reset(new Bech32Coder()); } + else if (mMode == "mainnet") { + mBech.reset(new Bech32Coder()); + } else { throw std::runtime_error("Wrong chain mode"); } @@ -60,7 +65,7 @@ struct TestcaseWrapper is_connected = false; } - if (!is_connected && mConfFactory.conf[config::option::CHAINMODE].as() == "regtest") { + if (!is_connected && mMode == "regtest") { StartRegtestBitcoinNode(); } @@ -68,12 +73,14 @@ struct TestcaseWrapper btc().GetWalletInfo(); } catch (...) { - btc().CreateWallet("testwallet"); + if (mMode != "mainnet") { + btc().CreateWallet("testwallet"); + } } - if (mConfFactory.conf[config::option::CHAINMODE].as() == "regtest") { + if (mMode == "regtest") { btc().GenerateToAddress(btc().GetNewAddress(), "151"); } - else if (mConfFactory.conf[config::option::CHAINMODE].as() == "testnet") { + else if (mMode == "testnet") { btc().WalletPassPhrase("********", "30"); } } From 260d3670663be41eb1ed6430632a57f7aa55fc62 Mon Sep 17 00:00:00 2001 From: l2xl Date: Tue, 11 Jul 2023 00:16:04 +0300 Subject: [PATCH 08/59] Add ChainApi::GetTx by txid --- src/api/Makefile.am | 1 + src/api/chain_api.cpp | 18 ++++++++++++++++++ src/api/chain_api.hpp | 1 + src/api/exechelper.cpp | 8 ++++---- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/api/Makefile.am b/src/api/Makefile.am index f7af9e6..d081e80 100644 --- a/src/api/Makefile.am +++ b/src/api/Makefile.am @@ -3,6 +3,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/$(NODE_PATH)/src \ -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/primitives \ -I$(top_srcdir)/$(NODE_PATH)/src/script \ -I$(top_srcdir)/$(NODE_PATH)/src/support \ -I$(top_srcdir)/$(SECP256K1_PATH)/include \ diff --git a/src/api/chain_api.cpp b/src/api/chain_api.cpp index bb56fc3..62950b7 100644 --- a/src/api/chain_api.cpp +++ b/src/api/chain_api.cpp @@ -1,6 +1,7 @@ #include "chain_api.hpp" #include "wallet_api.hpp" #include "exechelper.hpp" +#include "transaction.hpp" #include "script/script.h" #include "script/interpreter.h" @@ -28,6 +29,7 @@ namespace { const char* const SENDTOADDRESS = "sendtoaddress"; const char* const GETTXOUT = "gettxout"; const char* const SENDRAWTRANSACTION = "sendrawtransaction"; + const char* const GETRAWTRANSACTION = "getrawtransaction"; const char* const TESTMEMPOOLACCEPT = "testmempoolaccept"; const char* const GETNEWADDRESS = "getnewaddress"; const char* const GENERATETOADDRESS = "generatetoaddress"; @@ -233,6 +235,22 @@ std::string ChainApi::SpendTx(const CTransaction &tx) const return btc_exec.Run(); } +CTransaction ChainApi::GetTx(const std::string& txid) const +{ + ExecHelper btc_exec(m_cli_path, false); + + for(const auto& v: m_default) + { + btc_exec.Arguments().push_back(v); + } + + btc_exec.Arguments().emplace_back(GETRAWTRANSACTION); + btc_exec.Arguments().emplace_back(txid); + + CMutableTransaction tx = Deserialize(btc_exec.Run()); + return CTransaction(move(tx)); +} + std::string ChainApi::SpendSegwitTx(CMutableTransaction &tx, const std::vector &witness_stack) const { auto& witness = tx.vin[0].scriptWitness.stack; diff --git a/src/api/chain_api.hpp b/src/api/chain_api.hpp index c76118c..0b53a5b 100644 --- a/src/api/chain_api.hpp +++ b/src/api/chain_api.hpp @@ -47,6 +47,7 @@ class ChainApi { std::string SpendSegwitTx(CMutableTransaction &tx, const std::vector& witness_stack) const; std::string SpendTx(const CTransaction &tx) const; + CTransaction GetTx(const std::string& txid) const; std::string TestTxSequence(const std::vector &txs) const; std::string GetBlock(const std::string& block_hash, const std::string& verbosity = "2") const; diff --git a/src/api/exechelper.cpp b/src/api/exechelper.cpp index d974ac4..962b7ca 100644 --- a/src/api/exechelper.cpp +++ b/src/api/exechelper.cpp @@ -70,10 +70,10 @@ void ExecHelper::RunInternal() { buf << " (" << m_out << ")"; throw std::runtime_error(buf.str()); } - else - { - std::clog << ">>" << m_out << "<<" << std::endl; - } +// else +// { +// std::clog << ">>" << m_out << "<<" << std::endl; +// } } } From 592b048626f528c6be869ab88d460932ebc13f07 Mon Sep 17 00:00:00 2001 From: l2xl Date: Tue, 25 Jul 2023 20:55:05 +0300 Subject: [PATCH 09/59] Minor optimizations --- src/common/common_error.hpp | 1 + src/core/channel_keys.cpp | 2 +- src/core/channel_keys.hpp | 2 +- test/test-node/testnet/l15.conf | 2 +- test/test_case_wrapper.hpp | 8 ++++---- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/common/common_error.hpp b/src/common/common_error.hpp index 4201a83..215de5a 100644 --- a/src/common/common_error.hpp +++ b/src/common/common_error.hpp @@ -9,6 +9,7 @@ class Error : public std::exception { public: Error() noexcept = default; explicit Error(std::string&& details) noexcept : m_details(move(details)) {} + explicit Error(const char* const details) noexcept : m_details(details) {} ~Error() override = default; const char* what() const noexcept override = 0; diff --git a/src/core/channel_keys.cpp b/src/core/channel_keys.cpp index cbf7a4e..aa76385 100644 --- a/src/core/channel_keys.cpp +++ b/src/core/channel_keys.cpp @@ -290,7 +290,7 @@ signature ChannelKeys::SignSchnorr(const uint256& data) const return sig; } -signature ChannelKeys::SignTaprootTx(const CMutableTransaction &tx, uint32_t nin, std::vector&& spent_outputs, const CScript& spend_script, int hashtype) const +signature ChannelKeys::SignTaprootTx(const CMutableTransaction &tx, uint32_t nin, std::vector spent_outputs, const CScript& spend_script, int hashtype) const { uint256 sighash; PrecomputedTransactionData txdata; diff --git a/src/core/channel_keys.hpp b/src/core/channel_keys.hpp index 18d2084..6fe73a7 100644 --- a/src/core/channel_keys.hpp +++ b/src/core/channel_keys.hpp @@ -73,7 +73,7 @@ class ChannelKeys signature SignSchnorr(const uint256& data) const; - signature SignTaprootTx(const CMutableTransaction &tx, uint32_t nin, std::vector &&spent_outputs, + signature SignTaprootTx(const CMutableTransaction &tx, uint32_t nin, std::vector spent_outputs, const CScript &spend_script, int hashtype = SIGHASH_DEFAULT) const; }; diff --git a/test/test-node/testnet/l15.conf b/test/test-node/testnet/l15.conf index 18eb99d..fc6047e 100644 --- a/test/test-node/testnet/l15.conf +++ b/test/test-node/testnet/l15.conf @@ -1,7 +1,7 @@ mode=testnet [bitcoin] -rpcconnect=10.1.10.30 +rpcconnect=10.1.10.11 rpcport=18332 rpcuser=scott rpcpassword=tiger diff --git a/test/test_case_wrapper.hpp b/test/test_case_wrapper.hpp index acc26ea..6be08ae 100644 --- a/test/test_case_wrapper.hpp +++ b/test/test_case_wrapper.hpp @@ -73,16 +73,16 @@ struct TestcaseWrapper btc().GetWalletInfo(); } catch (...) { - if (mMode != "mainnet") { + if (mMode == "regtest") { btc().CreateWallet("testwallet"); } } if (mMode == "regtest") { btc().GenerateToAddress(btc().GetNewAddress(), "151"); } - else if (mMode == "testnet") { - btc().WalletPassPhrase("********", "30"); - } +// else if (mMode == "testnet") { +// btc().WalletPassPhrase("********", "30"); +// } } virtual ~TestcaseWrapper() From 8ed8903b842c4002a96cb9ad8f3a6e3cc673f4a6 Mon Sep 17 00:00:00 2001 From: l2xl Date: Tue, 22 Aug 2023 22:05:39 +0300 Subject: [PATCH 10/59] Pubkey only derivation for MasterKey class --- src/core/master_key.cpp | 72 ++++++++++++++++++++++++++++++++++- src/core/master_key.hpp | 10 ++++- test/core/test_derive_key.cpp | 27 +++++++++++-- 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/src/core/master_key.cpp b/src/core/master_key.cpp index 306ce0f..903fb34 100644 --- a/src/core/master_key.cpp +++ b/src/core/master_key.cpp @@ -60,7 +60,7 @@ void MasterKey::DeriveSelf(uint32_t branch) } } -ChannelKeys MasterKey::MakeKey(bool do_tweak) +ChannelKeys MasterKey::MakeKey(bool do_tweak) const { ChannelKeys res(m_ctx, mKey); @@ -71,6 +71,24 @@ ChannelKeys MasterKey::MakeKey(bool do_tweak) return res; } +ext_pubkey MasterKey::MakeExtPubKey() const +{ + ext_pubkey res; + + secp256k1_pubkey pubkey; + if (!secp256k1_ec_pubkey_create(m_ctx, &pubkey, mKey.data())) { + throw WrongKeyError(); + } + + size_t pubkeylen = 33; + if (!secp256k1_ec_pubkey_serialize(m_ctx, res.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { + throw KeyError("Master pubkey "); + } + memcpy(res.data() + 33, mChainCode.data(), 32); + + return res; +} + ChannelKeys MasterKey::Derive(const string &path, bool for_script) const { auto branches = spanparsing::Split(path, '/'); @@ -107,5 +125,57 @@ ChannelKeys MasterKey::Derive(const string &path, bool for_script) const return Derive(uint_branches, do_tweak); } +ext_pubkey MasterKey::DerivePubKey(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch) +{ + if (branch >= BIP32_HARDENED_KEY_LIMIT) { + throw std::invalid_argument("Can not derive pubkey using hardened algo"); + } + + secp256k1_pubkey pubkey; + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data(), 33)) { + throw WrongKeyError(); + } + + uint256 chaincode; + memcpy(chaincode.begin(), extpk.data() + 33, 32); + + uint8_t bip32hash[64]; + BIP32Hash(chaincode, branch, *extpk.data(), extpk.data() + 1, bip32hash); + + if (!secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, bip32hash)) { + throw KeyError("BIP32 pubkey derivation"); + } + + ext_pubkey res; + size_t pubkeylen = 33; + if (!secp256k1_ec_pubkey_serialize(ctx, res.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { + throw KeyError("derived pubkey"); + } + memcpy(res.data() + 33, bip32hash + 32, 32); + + return res; +} + +xonly_pubkey MasterKey::GetPubKey(const secp256k1_context *ctx, const ext_pubkey& extpk) +{ + secp256k1_pubkey pubkey; + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data(), 33)) { + throw WrongKeyError(); + } + + secp256k1_xonly_pubkey xonlypubkey; + int parity = 0; + if (!secp256k1_xonly_pubkey_from_pubkey(ctx, &xonlypubkey, &parity, &pubkey)) { + throw KeyError(); + } + + xonly_pubkey res; + if (!secp256k1_xonly_pubkey_serialize(ctx, res.data(), &xonlypubkey)) { + throw KeyError(); + } + + return res; +} + } // l15::core \ No newline at end of file diff --git a/src/core/master_key.hpp b/src/core/master_key.hpp index 2b06626..7b8c539 100644 --- a/src/core/master_key.hpp +++ b/src/core/master_key.hpp @@ -6,6 +6,10 @@ namespace l15::core { enum BIP86Tweak {AUTO, FORCE, SUPPRESS}; +typedef cex::fixsize_vector> ext_seckey; +typedef cex::fixsize_vector ext_pubkey; + + class MasterKey { public: @@ -26,7 +30,8 @@ class MasterKey MasterKey(const MasterKey&) = default; MasterKey(MasterKey&& ) = default; - ChannelKeys MakeKey(bool do_tweak); + ChannelKeys MakeKey(bool do_tweak) const; + ext_pubkey MakeExtPubKey() const; void DeriveSelf(uint32_t branch); @@ -44,6 +49,9 @@ class MasterKey } ChannelKeys Derive(const std::string& path, bool for_script = false) const; + + static ext_pubkey DerivePubKey(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch); + static xonly_pubkey GetPubKey(const secp256k1_context* ctx, const ext_pubkey& extpk); }; } // l15::core diff --git a/test/core/test_derive_key.cpp b/test/core/test_derive_key.cpp index 68fef96..904fc14 100644 --- a/test/core/test_derive_key.cpp +++ b/test/core/test_derive_key.cpp @@ -27,15 +27,17 @@ static const std::vector derive_branches = { static const std::string derive_path = "m/86'/2'/0'/0/0"; +ChannelKeys mockkey; + TEST_CASE("Seed") { - MasterKey extkey(seed); + MasterKey extkey(mockkey.Secp256k1Context(), seed); REQUIRE(bech.Encode(extkey.MakeKey(false).GetLocalPubKey()) == "tb1pz6zkdhjmar4x243yve469lex9htp8j2qzcu79s7mm420hddmwxssmngtnz"); } TEST_CASE("Derive") { - MasterKey master(seed); + MasterKey master(mockkey.Secp256k1Context(), seed); ChannelKeys derived = master.Derive(derive_branches, AUTO); @@ -44,9 +46,28 @@ TEST_CASE("Derive") TEST_CASE("DerivePath") { - MasterKey master(seed); + MasterKey master(mockkey.Secp256k1Context(), seed); ChannelKeys derived = master.Derive(derive_path, false); REQUIRE(bech.Encode(derived.GetLocalPubKey()) == "tb1ptnn4tufj4yr8ql0e8w8tye7juxzsndnxgnlehfk2p0skftzks20sncm2dz"); } + +TEST_CASE("DerivePubKey") +{ + const uint32_t magic_branch = 34565; + + MasterKey master(mockkey.Secp256k1Context(), seed); + + ext_pubkey extpubkey; + REQUIRE_NOTHROW(extpubkey = master.MakeExtPubKey()); + + REQUIRE_NOTHROW(master.DeriveSelf(magic_branch)); + ext_pubkey derived_extpk; + REQUIRE_NOTHROW(derived_extpk = MasterKey::DerivePubKey(mockkey.Secp256k1Context(), extpubkey, magic_branch)); + + xonly_pubkey derived_pk = MasterKey::GetPubKey(mockkey.Secp256k1Context(), derived_extpk); + ChannelKeys derived_keypair = master.MakeKey(false); + + REQUIRE(hex(derived_pk) == hex(derived_keypair.GetLocalPubKey())); +} From 2a71d3fca8bd10ae323ec83ecaf96c3d0a31fe7c Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 30 Aug 2023 21:58:18 +0300 Subject: [PATCH 11/59] PubKey derivation enchancements --- src/core/master_key.cpp | 54 +++++++++++++++++++++++++++++------ src/core/master_key.hpp | 5 +++- test/core/test_derive_key.cpp | 20 ++++++++++++- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/src/core/master_key.cpp b/src/core/master_key.cpp index 903fb34..e3c981e 100644 --- a/src/core/master_key.cpp +++ b/src/core/master_key.cpp @@ -17,14 +17,15 @@ MasterKey::MasterKey(const secp256k1_context* ctx, const bytevector& seed) : m_c memory_cleanse(vout, sizeof(vout)); } -MasterKey::MasterKey(const bytevector& seed) : m_ctx(ChannelKeys::GetStaticSecp256k1Context()), mKey(), mChainCode() -{ - uint8_t vout[64]; - CHMAC_SHA512{seed_hash_tag, sizeof(seed_hash_tag)}.Write(seed.data(), seed.size()).Finalize(vout); - mKey.assign(vout, vout + 32); - memcpy(mChainCode.begin(), vout + 32, 32); - memory_cleanse(vout, sizeof(vout)); -} +MasterKey::MasterKey(const bytevector& seed) : MasterKey(ChannelKeys::GetStaticSecp256k1Context(), seed) +{} + +MasterKey::MasterKey(const secp256k1_context* ctx, const ext_seckey& extkey) : m_ctx(ctx), mKey(extkey.begin(), extkey.begin() + 32), mChainCode(Span(const_cast(extkey.data()) + 32, 32)) +{} + +MasterKey::MasterKey(const ext_seckey& extkey) : MasterKey(ChannelKeys::GetStaticSecp256k1Context(), extkey) +{} + void MasterKey::DeriveSelf(uint32_t branch) { @@ -125,7 +126,7 @@ ChannelKeys MasterKey::Derive(const string &path, bool for_script) const return Derive(uint_branches, do_tweak); } -ext_pubkey MasterKey::DerivePubKey(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch) +ext_pubkey MasterKey::Derive(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch) { if (branch >= BIP32_HARDENED_KEY_LIMIT) { throw std::invalid_argument("Can not derive pubkey using hardened algo"); @@ -156,6 +157,41 @@ ext_pubkey MasterKey::DerivePubKey(const secp256k1_context* ctx, const ext_pubke return res; } +xonly_pubkey MasterKey::DerivePubKey(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch) +{ + if (branch >= BIP32_HARDENED_KEY_LIMIT) { + throw std::invalid_argument("Can not derive pubkey using hardened algo"); + } + + secp256k1_pubkey pubkey; + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data(), 33)) { + throw WrongKeyError(); + } + + uint256 chaincode; + memcpy(chaincode.begin(), extpk.data() + 33, 32); + + uint8_t bip32hash[64]; + BIP32Hash(chaincode, branch, *extpk.data(), extpk.data() + 1, bip32hash); + + if (!secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, bip32hash)) { + throw KeyError("BIP32 pubkey derivation"); + } + + secp256k1_xonly_pubkey xonlypubkey; + int parity = 0; + if (!secp256k1_xonly_pubkey_from_pubkey(ctx, &xonlypubkey, &parity, &pubkey)) { + throw KeyError(); + } + + xonly_pubkey res; + if (!secp256k1_xonly_pubkey_serialize(ctx, res.data(), &xonlypubkey)) { + throw KeyError(); + } + + return res; +} + xonly_pubkey MasterKey::GetPubKey(const secp256k1_context *ctx, const ext_pubkey& extpk) { secp256k1_pubkey pubkey; diff --git a/src/core/master_key.hpp b/src/core/master_key.hpp index 7b8c539..1224d64 100644 --- a/src/core/master_key.hpp +++ b/src/core/master_key.hpp @@ -26,6 +26,8 @@ class MasterKey public: MasterKey(const secp256k1_context* ctx, const bytevector& seed); explicit MasterKey(const bytevector& seed); + MasterKey(const secp256k1_context* ctx, const ext_seckey& extkey); + explicit MasterKey(const ext_seckey& extkey); MasterKey(const MasterKey&) = default; MasterKey(MasterKey&& ) = default; @@ -50,7 +52,8 @@ class MasterKey ChannelKeys Derive(const std::string& path, bool for_script = false) const; - static ext_pubkey DerivePubKey(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch); + static ext_pubkey Derive(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch); + static xonly_pubkey DerivePubKey(const secp256k1_context* ctx, const ext_pubkey& extpk, uint32_t branch); static xonly_pubkey GetPubKey(const secp256k1_context* ctx, const ext_pubkey& extpk); }; diff --git a/test/core/test_derive_key.cpp b/test/core/test_derive_key.cpp index 904fc14..5609031 100644 --- a/test/core/test_derive_key.cpp +++ b/test/core/test_derive_key.cpp @@ -62,9 +62,27 @@ TEST_CASE("DerivePubKey") ext_pubkey extpubkey; REQUIRE_NOTHROW(extpubkey = master.MakeExtPubKey()); + REQUIRE_NOTHROW(master.DeriveSelf(magic_branch)); + xonly_pubkey derived_pk; + REQUIRE_NOTHROW(derived_pk = MasterKey::DerivePubKey(mockkey.Secp256k1Context(), extpubkey, magic_branch)); + + ChannelKeys derived_keypair = master.MakeKey(false); + + REQUIRE(hex(derived_pk) == hex(derived_keypair.GetLocalPubKey())); +} + +TEST_CASE("DeriveExtPubKey") +{ + const uint32_t magic_branch = 34565; + + MasterKey master(mockkey.Secp256k1Context(), seed); + + ext_pubkey extpubkey; + REQUIRE_NOTHROW(extpubkey = master.MakeExtPubKey()); + REQUIRE_NOTHROW(master.DeriveSelf(magic_branch)); ext_pubkey derived_extpk; - REQUIRE_NOTHROW(derived_extpk = MasterKey::DerivePubKey(mockkey.Secp256k1Context(), extpubkey, magic_branch)); + REQUIRE_NOTHROW(derived_extpk = MasterKey::Derive(mockkey.Secp256k1Context(), extpubkey, magic_branch)); xonly_pubkey derived_pk = MasterKey::GetPubKey(mockkey.Secp256k1Context(), derived_extpk); ChannelKeys derived_keypair = master.MakeKey(false); From 69e93157fabe437caf5dffa24b1b4647fc6a496f Mon Sep 17 00:00:00 2001 From: l2xl Date: Tue, 26 Sep 2023 18:43:51 +0300 Subject: [PATCH 12/59] Bech32Coder::Encode() add parameter to select between bech32m and bech32 --- src/common/Makefile.am | 3 ++- src/common/utils.hpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 44c3943..906633c 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -1,7 +1,8 @@ VERSION_MODULE = version.cpp +BUILT_SOURCES = $(VERSION_MODULE) -.PHONY: $(VERSION_MODULE) +#.PHONY: $(VERSION_MODULE) $(VERSION_MODULE): $(top_srcdir)/version.sh Makefile echo '#include "version.hpp"' >$@ diff --git a/src/common/utils.hpp b/src/common/utils.hpp index 78501f4..309bb11 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -35,7 +35,7 @@ class IBech32Coder { enum ChainMode {MAINNET, TESTNET, REGTEST}; virtual ~IBech32Coder() = default; - virtual std::string Encode(const xonly_pubkey& pk) const = 0; + virtual std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const = 0; virtual xonly_pubkey Decode(const std::string& address) const = 0; }; @@ -54,11 +54,11 @@ template class Bech32Code typedef Hrp hrp; ~Bech32Coder() override = default; - std::string Encode(const xonly_pubkey& pk) const override { + std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const override { std::vector bech32buf = {1}; bech32buf.reserve(1 + ((pk.end() - pk.begin()) * 8 + 4) / 5); ConvertBits<8, 5, true>([&](unsigned char c) { bech32buf.push_back(c); }, pk.begin(), pk.end()); - return bech32::Encode(bech32::Encoding::BECH32M, hrp::value, bech32buf); + return bech32::Encode(encoding, hrp::value, bech32buf); } xonly_pubkey Decode(const std::string& address) const override { From 03a683e005576deae4a950b86fe477217c5e54a7 Mon Sep 17 00:00:00 2001 From: l2xl Date: Thu, 28 Sep 2023 18:14:41 +0300 Subject: [PATCH 13/59] Fix ChainApi::GetNewAddress() arg processing --- src/api/chain_api.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/api/chain_api.cpp b/src/api/chain_api.cpp index 62950b7..2f16334 100644 --- a/src/api/chain_api.cpp +++ b/src/api/chain_api.cpp @@ -317,9 +317,7 @@ std::string ChainApi::GetNewAddress(const std::string& label, const std::string& }); btc_exec.Arguments().emplace_back(GETNEWADDRESS); - if (!label.empty()) { - btc_exec.Arguments().emplace_back(label); - } + btc_exec.Arguments().emplace_back(label); btc_exec.Arguments().emplace_back(address_type); return btc_exec.Run(); From 06ad65597c751b1461ea3d1d055622c405f41684 Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 4 Oct 2023 17:08:29 +0300 Subject: [PATCH 14/59] Some enchancements --- contrib/cex/safe_ptr.hpp | 34 ++++++++++++++++++++++++++++++++++ src/common/utils.hpp | 19 ++++++++++++------- src/core/master_key.hpp | 3 ++- 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 contrib/cex/safe_ptr.hpp diff --git a/contrib/cex/safe_ptr.hpp b/contrib/cex/safe_ptr.hpp new file mode 100644 index 0000000..87ae170 --- /dev/null +++ b/contrib/cex/safe_ptr.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace cex { + +template +class safe_ptr +{ + std::weak_ptr m_ptr; +public: + + safe_ptr() noexcept = delete; + safe_ptr(const safe_ptr& ) = default; + safe_ptr(safe_ptr&&) noexcept = default; + + safe_ptr(std::weak_ptr ptr) : m_ptr(move(ptr)) {} + safe_ptr(std::shared_ptr ptr) : m_ptr(move(ptr)) {} + + safe_ptr& operator=(const safe_ptr&) = default; + safe_ptr& operator=(safe_ptr&&) = default; + + std::shared_ptr lock() const + { + auto p = m_ptr.lock(); + if (p) return p; + else throw E(M); + } + + const std::weak_ptr& ref() const + { return m_ptr; } +}; + +} \ No newline at end of file diff --git a/src/common/utils.hpp b/src/common/utils.hpp index 309bb11..9a06514 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -3,6 +3,8 @@ #include #include +#include "smartinserter.hpp" + #include "bech32.h" #include "util/strencodings.h" #include "crypto/sha256.h" @@ -35,8 +37,10 @@ class IBech32Coder { enum ChainMode {MAINNET, TESTNET, REGTEST}; virtual ~IBech32Coder() = default; - virtual std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const = 0; - virtual xonly_pubkey Decode(const std::string& address) const = 0; + std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const + { return Encode(pk.get_vector(), encoding); } + virtual std::string Encode(const bytevector& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const = 0; + virtual bytevector Decode(const std::string& address) const = 0; }; template struct Hrp; @@ -54,14 +58,15 @@ template class Bech32Code typedef Hrp hrp; ~Bech32Coder() override = default; - std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const override { - std::vector bech32buf = {1}; + using IBech32Coder::Encode; + std::string Encode(const bytevector& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const override { + std::vector bech32buf = {(encoding == bech32::Encoding::BECH32) ? (uint8_t)0 : (uint8_t)1}; bech32buf.reserve(1 + ((pk.end() - pk.begin()) * 8 + 4) / 5); ConvertBits<8, 5, true>([&](unsigned char c) { bech32buf.push_back(c); }, pk.begin(), pk.end()); return bech32::Encode(encoding, hrp::value, bech32buf); } - xonly_pubkey Decode(const std::string& address) const override { + bytevector Decode(const std::string& address) const override { bech32::DecodeResult bech_result = bech32::Decode(address); if(bech_result.hrp != hrp::value) { @@ -80,8 +85,8 @@ template class Bech32Code throw std::runtime_error("Version 1+ witness address must use Bech32m checksum"); } - xonly_pubkey data; - auto I = data.begin(); + bytevector data; + auto I = cex::smartinserter(data, data.end()); if(!ConvertBits<5, 8, false>([&](unsigned char c) { *I++ = c; }, bech_result.data.begin() + 1, bech_result.data.end())) { throw std::runtime_error(std::string("Wrong bech32 data: ") + address); diff --git a/src/core/master_key.hpp b/src/core/master_key.hpp index 1224d64..8809077 100644 --- a/src/core/master_key.hpp +++ b/src/core/master_key.hpp @@ -15,6 +15,7 @@ class MasterKey public: static const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; static const uint32_t BIP32_BRANCH_MASK = 0x7fffffff; + static const uint32_t BIP84_P2WPKH_ACCOUNT = 84; static const uint32_t BIP86_TAPROOT_ACCOUNT = 86; private: const secp256k1_context* m_ctx; @@ -37,7 +38,7 @@ class MasterKey void DeriveSelf(uint32_t branch); - template + template ChannelKeys Derive(const T& branches, BIP86Tweak bip86_tweak) const { MasterKey branchKey(*this); From fff7f69ed5870946abd4287a9973846cbaa285b8 Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 4 Oct 2023 22:38:32 +0300 Subject: [PATCH 15/59] Catch2 improved exception reporting --- contrib/catch/catch.hpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/contrib/catch/catch.hpp b/contrib/catch/catch.hpp index ccd5749..48a3f03 100644 --- a/contrib/catch/catch.hpp +++ b/contrib/catch/catch.hpp @@ -10690,6 +10690,30 @@ void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator } #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) + +template +std::string translateIfNestedException(E &e, std::size_t level) { + try { + std::rethrow_if_nested(e); + return std::string(); + } + catch( std::exception& e1 ) { + return std::string("\n") + std::string(level*2, ' ') + e1.what() + translateIfNestedException(e1, level + 1); + } + catch( std::string& msg ) { + return std::string("\n") + std::string(level*2, ' ') + msg; + } + catch( std::nested_exception& e1 ) { + return std::string("\n") + std::string(level*2, ' ') + "Unknown exception" + translateIfNestedException(e1, level + 1); + } + catch( const char* msg ) { + return std::string("\n") + std::string(level*2, ' ') + msg; + } + catch(...) { + return std::string("\n") + std::string(level*2, ' ') + "Unknown exception"; + } +} + std::string ExceptionTranslatorRegistry::translateActiveException() const { try { #ifdef __OBJC__ @@ -10719,7 +10743,10 @@ std::string ExceptionTranslatorRegistry::translateActiveException() const { std::rethrow_exception(std::current_exception()); } catch( std::exception& ex ) { - return ex.what(); + return std::string(ex.what()) + translateIfNestedException(ex, 1); + } + catch( std::nested_exception& ex ) { + return "Unknown exception" + translateIfNestedException(ex, 1); } catch( std::string& msg ) { return msg; From f0e2058358c33a8927d9a16725525fad8dbc6b44 Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 4 Oct 2023 22:51:11 +0300 Subject: [PATCH 16/59] Fix bech32 decoder --- src/common/utils.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/utils.hpp b/src/common/utils.hpp index 9a06514..ae3bb8b 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -86,8 +86,9 @@ template class Bech32Code } bytevector data; + data.reserve(32); auto I = cex::smartinserter(data, data.end()); - if(!ConvertBits<5, 8, false>([&](unsigned char c) { *I++ = c; }, bech_result.data.begin() + 1, bech_result.data.end())) + if(!ConvertBits<5, 8, false>([&](unsigned char c) { *I = c; ++I; }, bech_result.data.begin() + 1, bech_result.data.end())) { throw std::runtime_error(std::string("Wrong bech32 data: ") + address); } From 174b0bc1fe24c80500c0fb39b14ee5ed713c8b60 Mon Sep 17 00:00:00 2001 From: l2xl Date: Fri, 6 Oct 2023 22:13:48 +0300 Subject: [PATCH 17/59] Fix smartinserter for WASM --- contrib/cex/smartinserter.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/cex/smartinserter.hpp b/contrib/cex/smartinserter.hpp index 549040a..f391295 100644 --- a/contrib/cex/smartinserter.hpp +++ b/contrib/cex/smartinserter.hpp @@ -66,9 +66,9 @@ class insert_iterator typedef insert_reference reference; typedef typename traits_type::pointer pointer; -#if __cplusplus > 201703L && __cpp_lib_concepts - using iterator_concept = std::__detail::__iter_concept; -#endif +//#if __cplusplus > 201703L && __cpp_lib_concepts +// using iterator_concept = std::__detail::__iter_concept; +//#endif CEXCXX20_CONSTEXPR From dd34b9f718dfb0c6cf002a30999942a15515c482 Mon Sep 17 00:00:00 2001 From: l2xl Date: Thu, 19 Oct 2023 01:53:05 +0300 Subject: [PATCH 18/59] Fix ChannelKeys copying ctor --- src/core/channel_keys.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/channel_keys.hpp b/src/core/channel_keys.hpp index 6fe73a7..c449855 100644 --- a/src/core/channel_keys.hpp +++ b/src/core/channel_keys.hpp @@ -39,6 +39,8 @@ class ChannelKeys ChannelKeys(ChannelKeys &&old) noexcept: m_ctx(old.m_ctx), m_local_sk(std::move(old.m_local_sk)), m_local_pk(std::move(old.m_local_pk)), m_pubkey_agg(std::move(old.m_pubkey_agg)) {} + ChannelKeys& operator=(const ChannelKeys& o) = default; + ChannelKeys& operator=(ChannelKeys&& old) noexcept { m_local_sk = std::move(old.m_local_sk); From d3dc45459f108928fd51c79169ca6a1de5f979bf Mon Sep 17 00:00:00 2001 From: l2xl Date: Tue, 24 Oct 2023 00:59:00 +0300 Subject: [PATCH 19/59] MasterKey minor fix --- src/core/master_key.hpp | 6 +++--- test/core/test_derive_key.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/master_key.hpp b/src/core/master_key.hpp index 8809077..995e9a2 100644 --- a/src/core/master_key.hpp +++ b/src/core/master_key.hpp @@ -15,8 +15,8 @@ class MasterKey public: static const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000; static const uint32_t BIP32_BRANCH_MASK = 0x7fffffff; - static const uint32_t BIP84_P2WPKH_ACCOUNT = 84; - static const uint32_t BIP86_TAPROOT_ACCOUNT = 86; + static const uint32_t BIP84_P2WPKH = 84; + static const uint32_t BIP86_TAPROOT = 86; private: const secp256k1_context* m_ctx; seckey mKey; @@ -47,7 +47,7 @@ class MasterKey branchKey.DeriveSelf(b); } - bool do_tweak = (bip86_tweak == FORCE) || (bip86_tweak == AUTO && (branches.front() & BIP32_BRANCH_MASK) == BIP86_TAPROOT_ACCOUNT); + bool do_tweak = (bip86_tweak == FORCE) || (bip86_tweak == AUTO && (branches.front() & BIP32_BRANCH_MASK) == BIP86_TAPROOT); return branchKey.MakeKey(do_tweak); } diff --git a/test/core/test_derive_key.cpp b/test/core/test_derive_key.cpp index 5609031..8c4651c 100644 --- a/test/core/test_derive_key.cpp +++ b/test/core/test_derive_key.cpp @@ -20,7 +20,7 @@ static const bytevector seed = unhex( static const auto bech = Bech32Coder(); static const std::vector derive_branches = { - MasterKey::BIP86_TAPROOT_ACCOUNT | MasterKey::BIP32_HARDENED_KEY_LIMIT, + MasterKey::BIP86_TAPROOT | MasterKey::BIP32_HARDENED_KEY_LIMIT, 2 | MasterKey::BIP32_HARDENED_KEY_LIMIT, MasterKey::BIP32_HARDENED_KEY_LIMIT, 0, 0}; From 1ec28cb3641ba269e2bd08f0b70044bcc8898aa4 Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 1 Nov 2023 21:00:50 +0300 Subject: [PATCH 20/59] fix l15::signature construction/assignment --- src/common/common.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/common/common.hpp b/src/common/common.hpp index 531eb7e..a49f8b5 100644 --- a/src/common/common.hpp +++ b/src/common/common.hpp @@ -35,6 +35,13 @@ typedef std::vector stringvector; class signature: public bytevector { public: signature() : bytevector(65) { resize(64); } + signature(const signature&) = default; + signature(signature&& ) noexcept = default; + signature(const bytevector& v) : bytevector(v) {} + signature(bytevector&& v) noexcept : bytevector(move(v)) {} + + signature& operator=(const signature&) = default; + signature& operator=(signature&& ) noexcept = default; }; typedef cex::fixsize_vector> seckey; From cb2156d1351eff236d5d36ac05e81d3bb7c8cbb6 Mon Sep 17 00:00:00 2001 From: l2xl Date: Fri, 22 Dec 2023 23:37:09 +0300 Subject: [PATCH 21/59] Minor changes --- src/common/utils.cpp | 3 ++- src/core/script_merkle_tree.hpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 49c2cd2..6bc44e5 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -8,6 +8,7 @@ #include "feerate.h" #include "common_error.hpp" +#include "policy.h" #include #include @@ -143,7 +144,7 @@ CAmount Dust(CAmount fee_rate) CAmount CalculateOutputAmount(CAmount input_amount, CAmount fee_rate, const CMutableTransaction& tx) { auto fee = CalculateTxFee(fee_rate, tx); - if ((fee + Dust(3000)) >= input_amount) { + if ((fee + Dust(DUST_RELAY_TX_FEE)) >= input_amount) { std::ostringstream buf; buf << "Input amount too small (dust): " << FormatAmount(input_amount) << ", calculated fee: " << FormatAmount(fee); throw TransactionError(buf.str()); diff --git a/src/core/script_merkle_tree.hpp b/src/core/script_merkle_tree.hpp index 0295675..893872d 100644 --- a/src/core/script_merkle_tree.hpp +++ b/src/core/script_merkle_tree.hpp @@ -24,10 +24,15 @@ uint256 TapLeafHash(const CScript &script); enum class TreeBalanceType {WEIGHTED /*, BALANCED*/}; class ScriptMerkleTree { - const TreeBalanceType mTreeType; + TreeBalanceType mTreeType; std::vector mScripts; public: explicit ScriptMerkleTree(const TreeBalanceType treeType, std::vector&& scripts = {}): mTreeType(treeType), mScripts(std::move(scripts)) {} + ScriptMerkleTree(const ScriptMerkleTree& ) = default; + ScriptMerkleTree(ScriptMerkleTree&& ) noexcept = default; + + ScriptMerkleTree& operator=(const ScriptMerkleTree& ) = default; + ScriptMerkleTree& operator=(ScriptMerkleTree&& ) noexcept = default; std::vector& GetScripts() { return mScripts; } const std::vector& GetScripts() const { return mScripts; } From 207c7ea7023b9a4aa8cb36150faf7d85db3c3160 Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 10 Jan 2024 00:17:39 +0300 Subject: [PATCH 22/59] GetAddress(chain_mode, pubkeyscript) for SegWit only --- src/core/transaction.cpp | 29 +++++++++++++++++++++++++++++ src/core/transaction.hpp | 2 ++ 2 files changed, 31 insertions(+) diff --git a/src/core/transaction.cpp b/src/core/transaction.cpp index 357a440..c11a571 100644 --- a/src/core/transaction.cpp +++ b/src/core/transaction.cpp @@ -63,4 +63,33 @@ std::string GetTaprootAddress(const std::string& chain_mode, const std::string& } } +std::string GetAddress(const std::string& chain_mode, const bytevector& pubkeyscript) +{ + int witver; + bytevector witnessprogram; + CScript script(pubkeyscript.begin(), pubkeyscript.end()); + bool segwit = script.IsWitnessProgram(witver, witnessprogram); + if (segwit) { + if (chain_mode == "testnet") { + Bech32Coder bech32; + return bech32.Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); + } + else if (chain_mode == "mainnet") { + Bech32Coder bech32; + return bech32.Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); + } + else if (chain_mode == "regtest") { + Bech32Coder bech32; + return bech32.Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); + } + else { + throw IllegalArgumentError(std::string(chain_mode)); + } + } + else { + return ""; + //throw TransactionError("Not SegWit"); + } +} + } // core diff --git a/src/core/transaction.hpp b/src/core/transaction.hpp index 6dc3ae8..93cb8ab 100644 --- a/src/core/transaction.hpp +++ b/src/core/transaction.hpp @@ -12,6 +12,8 @@ bool IsTaproot(const CTxOut& out); std::string GetTaprootPubKey(const CTxOut& out); std::string GetTaprootAddress(const std::string& chain_mode, const std::string& pubkey); +std::string GetAddress(const std::string& chain_mode, const bytevector& pubkeyscript); + } // l15::core From 0a4423b220365df0b03140b06d3f0f108d19d65b Mon Sep 17 00:00:00 2001 From: l2xl Date: Wed, 10 Jan 2024 00:51:50 +0300 Subject: [PATCH 23/59] xonly_pubkey ctor with iterators --- src/common/common.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/common.hpp b/src/common/common.hpp index a49f8b5..32cd5a2 100644 --- a/src/common/common.hpp +++ b/src/common/common.hpp @@ -58,6 +58,8 @@ class xonly_pubkey : public cex::fixsize_vector xonly_pubkey(xonly_pubkey&&) noexcept = default; xonly_pubkey(const base::base& v) : cex::fixsize_vector(v) {} xonly_pubkey(base::base&& v) noexcept : cex::fixsize_vector(move(v)) {} + template + xonly_pubkey(I b, I e, const allocator_type& a = allocator_type()) : base(b, e, a) {} xonly_pubkey(const secp256k1_context *ctx, const secp256k1_xonly_pubkey &pk) : base() { set(ctx, pk); } From 37fbde0456ec17994b609b050a845ec6f605b808 Mon Sep 17 00:00:00 2001 From: l2xl Date: Fri, 12 Jan 2024 01:51:31 +0300 Subject: [PATCH 24/59] Change core::ext_pubkey format --- src/core/master_key.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/master_key.cpp b/src/core/master_key.cpp index e3c981e..82d3ef7 100644 --- a/src/core/master_key.cpp +++ b/src/core/master_key.cpp @@ -81,11 +81,11 @@ ext_pubkey MasterKey::MakeExtPubKey() const throw WrongKeyError(); } + memcpy(res.data(), mChainCode.data(), 32); size_t pubkeylen = 33; - if (!secp256k1_ec_pubkey_serialize(m_ctx, res.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { + if (!secp256k1_ec_pubkey_serialize(m_ctx, res.data()+32, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { throw KeyError("Master pubkey "); } - memcpy(res.data() + 33, mChainCode.data(), 32); return res; } @@ -133,15 +133,15 @@ ext_pubkey MasterKey::Derive(const secp256k1_context* ctx, const ext_pubkey& ext } secp256k1_pubkey pubkey; - if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data(), 33)) { + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data()+32, 33)) { throw WrongKeyError(); } uint256 chaincode; - memcpy(chaincode.begin(), extpk.data() + 33, 32); + memcpy(chaincode.begin(), extpk.data(), 32); uint8_t bip32hash[64]; - BIP32Hash(chaincode, branch, *extpk.data(), extpk.data() + 1, bip32hash); + BIP32Hash(chaincode, branch, extpk.data()[32], extpk.data() + 33, bip32hash); if (!secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, bip32hash)) { throw KeyError("BIP32 pubkey derivation"); @@ -149,10 +149,10 @@ ext_pubkey MasterKey::Derive(const secp256k1_context* ctx, const ext_pubkey& ext ext_pubkey res; size_t pubkeylen = 33; - if (!secp256k1_ec_pubkey_serialize(ctx, res.data(), &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { + memcpy(res.data(), bip32hash + 32, 32); + if (!secp256k1_ec_pubkey_serialize(ctx, res.data() + 32, &pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED)) { throw KeyError("derived pubkey"); } - memcpy(res.data() + 33, bip32hash + 32, 32); return res; } @@ -164,15 +164,15 @@ xonly_pubkey MasterKey::DerivePubKey(const secp256k1_context* ctx, const ext_pub } secp256k1_pubkey pubkey; - if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data(), 33)) { + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data() + 32, 33)) { throw WrongKeyError(); } uint256 chaincode; - memcpy(chaincode.begin(), extpk.data() + 33, 32); + memcpy(chaincode.begin(), extpk.data(), 32); uint8_t bip32hash[64]; - BIP32Hash(chaincode, branch, *extpk.data(), extpk.data() + 1, bip32hash); + BIP32Hash(chaincode, branch, extpk.data()[32], extpk.data() + 33, bip32hash); if (!secp256k1_ec_pubkey_tweak_add(ctx, &pubkey, bip32hash)) { throw KeyError("BIP32 pubkey derivation"); @@ -195,7 +195,7 @@ xonly_pubkey MasterKey::DerivePubKey(const secp256k1_context* ctx, const ext_pub xonly_pubkey MasterKey::GetPubKey(const secp256k1_context *ctx, const ext_pubkey& extpk) { secp256k1_pubkey pubkey; - if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data(), 33)) { + if (!secp256k1_ec_pubkey_parse(ctx, &pubkey, extpk.data() + 32, 33)) { throw WrongKeyError(); } From 32f4ee009782252328f28b033275f9a848a87eae Mon Sep 17 00:00:00 2001 From: l2xl Date: Fri, 19 Jan 2024 19:51:57 +0300 Subject: [PATCH 25/59] compile time Dust calculation --- src/api/Makefile.am | 1 + src/common/utils.cpp | 6 ------ src/common/utils.hpp | 5 ++++- src/core/Makefile.am | 1 + test/core/Makefile.am | 1 + 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/api/Makefile.am b/src/api/Makefile.am index d081e80..169d262 100644 --- a/src/api/Makefile.am +++ b/src/api/Makefile.am @@ -2,6 +2,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/$(NODE_PATH)/src \ -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/policy \ -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ -I$(top_srcdir)/$(NODE_PATH)/src/primitives \ -I$(top_srcdir)/$(NODE_PATH)/src/script \ diff --git a/src/common/utils.cpp b/src/common/utils.cpp index 6bc44e5..edf7c70 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -135,12 +135,6 @@ CAmount CalculateTxFee(CAmount fee_rate, const CMutableTransaction& tx) return CFeeRate(fee_rate).GetFee(vsize); } -CAmount Dust(CAmount fee_rate) -{ - // See bitcoin/src/policy/policy.cpp:57 - return CFeeRate(fee_rate).GetFee(43 + 32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4); -} - CAmount CalculateOutputAmount(CAmount input_amount, CAmount fee_rate, const CMutableTransaction& tx) { auto fee = CalculateTxFee(fee_rate, tx); diff --git a/src/common/utils.hpp b/src/common/utils.hpp index ae3bb8b..c6943a6 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -13,6 +13,9 @@ #include "amount.h" #include "common.hpp" +#include "feerate.h" +#include "consensus.h" +#include "policy.h" namespace l15 { @@ -20,7 +23,7 @@ CAmount ParseAmount(const std::string& amountstr); std::string FormatAmount(CAmount amount); CAmount CalculateOutputAmount(CAmount input_amount, CAmount fee_rate, const CMutableTransaction&); CAmount CalculateTxFee(CAmount fee_rate, const CMutableTransaction& tx); -CAmount Dust(CAmount fee_rate); +constexpr CAmount Dust(const CAmount fee_rate = DUST_RELAY_TX_FEE) {return CFeeRate(fee_rate).GetFee(43 + 32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);} bytevector ScriptHash(const CScript &script); bytevector CreatePreimage(); diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 4bd6f2b..258b054 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -3,6 +3,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/$(NODE_PATH)/src \ -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ + -I$(top_srcdir)/$(NODE_PATH)/src/policy \ -I$(top_srcdir)/$(NODE_PATH)/src/primitives \ -I$(top_srcdir)/$(NODE_PATH)/src/script \ -I$(top_srcdir)/$(NODE_PATH)/src/support \ diff --git a/test/core/Makefile.am b/test/core/Makefile.am index cf1fc64..a8c1988 100644 --- a/test/core/Makefile.am +++ b/test/core/Makefile.am @@ -7,6 +7,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/$(SECP256K1_PATH)/include \ -I$(top_srcdir)/$(NODE_PATH)/src \ -I$(top_srcdir)/$(NODE_PATH)/src/univalue/include \ + -I$(top_srcdir)/$(NODE_PATH)/src/policy \ -I$(top_srcdir)/$(NODE_PATH)/src/consensus \ -I$(top_srcdir)/$(NODE_PATH)/src/script \ -I$(top_srcdir)/$(NODE_PATH)/src/support \ From d2e1c644a88df6989c18d48e4930600500a4ec5f Mon Sep 17 00:00:00 2001 From: l2xl Date: Mon, 22 Jan 2024 02:17:25 +0300 Subject: [PATCH 26/59] Add CheckMiningFee() util for onchain transaction --- src/common/utils.cpp | 6 +++++- src/common/utils.hpp | 2 +- test/testutils.hpp | 21 +++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test/testutils.hpp diff --git a/src/common/utils.cpp b/src/common/utils.cpp index edf7c70..ecc7c47 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -124,7 +124,8 @@ std::string FormatAmount(CAmount amount) return res.substr(0, res.length() - cut_zeroes); } -CAmount CalculateTxFee(CAmount fee_rate, const CMutableTransaction& tx) +template +CAmount CalculateTxFee(CAmount fee_rate, const T& tx) { size_t tx_size = GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS); size_t tx_wit_size = GetSerializeSize(tx, PROTOCOL_VERSION); @@ -135,6 +136,9 @@ CAmount CalculateTxFee(CAmount fee_rate, const CMutableTransaction& tx) return CFeeRate(fee_rate).GetFee(vsize); } +template CAmount CalculateTxFee(CAmount fee_rate, const CMutableTransaction& ); +template CAmount CalculateTxFee(CAmount fee_rate, const CTransaction& ); + CAmount CalculateOutputAmount(CAmount input_amount, CAmount fee_rate, const CMutableTransaction& tx) { auto fee = CalculateTxFee(fee_rate, tx); diff --git a/src/common/utils.hpp b/src/common/utils.hpp index c6943a6..44cef39 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -22,7 +22,7 @@ namespace l15 { CAmount ParseAmount(const std::string& amountstr); std::string FormatAmount(CAmount amount); CAmount CalculateOutputAmount(CAmount input_amount, CAmount fee_rate, const CMutableTransaction&); -CAmount CalculateTxFee(CAmount fee_rate, const CMutableTransaction& tx); +template CAmount CalculateTxFee(CAmount fee_rate, const T& tx); constexpr CAmount Dust(const CAmount fee_rate = DUST_RELAY_TX_FEE) {return CFeeRate(fee_rate).GetFee(43 + 32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);} bytevector ScriptHash(const CScript &script); diff --git a/test/testutils.hpp b/test/testutils.hpp new file mode 100644 index 0000000..e92867b --- /dev/null +++ b/test/testutils.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "feerate.h" + +#include "utils.hpp" + +namespace l15 { + +template +CAmount CheckMiningFee(CAmount funds_in, const T tx, CAmount feerate) +{ + CAmount funds_out = 0; + funds_out = std::accumulate(tx.vout.begin(), tx.vout.end(), funds_out, [](CAmount prev, const auto& out) { return prev + out.nValue;}); + CAmount fee = CalculateTxFee(feerate, tx); + + return funds_in - funds_out - fee; +} + +} \ No newline at end of file From 65155ec617e62cde51ccccd950ffd68c2264eec5 Mon Sep 17 00:00:00 2001 From: l2xl Date: Thu, 14 Mar 2024 03:21:20 +0300 Subject: [PATCH 27/59] Minor utils and testenv improvements --- src/tools/nodehelper.cpp | 3 +-- test/test-node/regtest/bitcoin/bitcoin.conf | 7 +++---- test/test-node/regtest/l15.conf | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/tools/nodehelper.cpp b/src/tools/nodehelper.cpp index 23f8d5e..e13f477 100644 --- a/src/tools/nodehelper.cpp +++ b/src/tools/nodehelper.cpp @@ -11,6 +11,7 @@ void StartNode(ChainMode mode, ExecHelper& node_exec, const CLI::App& options) { node_exec.Arguments().clear(); node_exec.Arguments().emplace_back("-daemon"); + node_exec.Arguments().emplace_back("-daemonwait"); for(const auto opt: options.get_options([](const CLI::Option* o){ return o && !o->check_name("--help"); })) { @@ -21,8 +22,6 @@ void StartNode(ChainMode mode, ExecHelper& node_exec, const CLI::App& options) else if(mode == ChainMode::MODE_TESTNET) node_exec.Arguments().emplace_back("-testnet"); node_exec.Run(); - - std::this_thread::sleep_for(std::chrono::seconds(5)); } void StopNode(ChainMode mode, ExecHelper& cli_exec, const CLI::App& options) diff --git a/test/test-node/regtest/bitcoin/bitcoin.conf b/test/test-node/regtest/bitcoin/bitcoin.conf index 5cc94d7..3131c58 100644 --- a/test/test-node/regtest/bitcoin/bitcoin.conf +++ b/test/test-node/regtest/bitcoin/bitcoin.conf @@ -1,10 +1,9 @@ -regtest=1 +txindex=1 dnsseed=0 upnp=0 [regtest] rpcport=19003 server=1 rpcallowip=127.0.0.1 -rpcuser=rpcuser -rpcpassword=test -fallbackfee=0.00015 +rpcauth=scott:3b76f3884f2fa1600e4a31dd49dcba57$9465d6cfd161e0691010dba12232afb6d49a5d66c8eadaca2a9650eacc967402 +fallbackfee=0.00001 diff --git a/test/test-node/regtest/l15.conf b/test/test-node/regtest/l15.conf index 09f1420..cbc2bfe 100644 --- a/test/test-node/regtest/l15.conf +++ b/test/test-node/regtest/l15.conf @@ -17,6 +17,6 @@ conf=bitcoin.conf [bitcoin] rpcconnect=127.0.0.1 rpcport=19003 -rpcuser=rpcuser -rpcpassword=test +rpcuser=scott +rpcpassword=tiger From f7533f5d1e6285a38458c91a7eda2933760afe70 Mon Sep 17 00:00:00 2001 From: l2xl Date: Thu, 18 Apr 2024 22:14:24 +0300 Subject: [PATCH 28/59] Remove unnessesary link options for WASM linker --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cd2ae2f..f3cce28 100644 --- a/configure.ac +++ b/configure.ac @@ -202,7 +202,7 @@ fi if test "$enable_wasm_binding" = "yes"; then CPPFLAGS="$DEBUG_CPPFLAGS $CPPFLAGS" CXXFLAGS="$DEBUG_CXXFLAGS $CXXFLAGS -fexceptions -Wno-unqualified-std-cast-call" - LDFLAGS="$LDFLAGS -fexceptions -sEXPORT_EXCEPTION_HANDLING_HELPERS -sLLD_REPORT_UNDEFINED -sEXPORTED_FUNCTIONS=['_malloc'] -sEXPORT_NAME='L15' -sMODULARIZE=1 -sNO_FILESYSTEM=1" + LDFLAGS="$LDFLAGS -fexceptions" if test "$enable_debug" != "yes"; then CFLAGS=" -O3 $CFLAGS" From 7042736219d1900529057f9c5fae96c60aedb726 Mon Sep 17 00:00:00 2001 From: l2xl Date: Fri, 7 Jun 2024 17:54:17 +0300 Subject: [PATCH 29/59] Refactor Bech32Coder --- configure.ac | 2 +- src/common/utils.cpp | 13 ++++---- src/common/utils.hpp | 60 +++++++++++++++++++---------------- src/core/transaction.cpp | 18 ++++------- src/tools/nodehelper.cpp | 15 +++++---- src/tools/nodehelper.hpp | 6 ++-- test/core/test_derive_key.cpp | 2 +- test/test_case_wrapper.hpp | 29 ++++++----------- 8 files changed, 68 insertions(+), 77 deletions(-) diff --git a/configure.ac b/configure.ac index f3cce28..cd2ae2f 100644 --- a/configure.ac +++ b/configure.ac @@ -202,7 +202,7 @@ fi if test "$enable_wasm_binding" = "yes"; then CPPFLAGS="$DEBUG_CPPFLAGS $CPPFLAGS" CXXFLAGS="$DEBUG_CXXFLAGS $CXXFLAGS -fexceptions -Wno-unqualified-std-cast-call" - LDFLAGS="$LDFLAGS -fexceptions" + LDFLAGS="$LDFLAGS -fexceptions -sEXPORT_EXCEPTION_HANDLING_HELPERS -sLLD_REPORT_UNDEFINED -sEXPORTED_FUNCTIONS=['_malloc'] -sEXPORT_NAME='L15' -sMODULARIZE=1 -sNO_FILESYSTEM=1" if test "$enable_debug" != "yes"; then CFLAGS=" -O3 $CFLAGS" diff --git a/src/common/utils.cpp b/src/common/utils.cpp index ecc7c47..ff91ca1 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -16,12 +16,12 @@ namespace l15 { -const char* const Hrp::value = "bc"; -const char* const Hrp::value = "tb"; -const char* const Hrp::value = "bcrt"; -const char* const Hrp::value = "l15"; -const char* const Hrp::value = "l15t"; -const char* const Hrp::value = "l15rt"; +const char* const Hrp::value = "bc"; +const char* const Hrp::value = "tb"; +const char* const Hrp::value = "bcrt"; +const char* const Hrp::value = "l15"; +const char* const Hrp::value = "l15t"; +const char* const Hrp::value = "l15rt"; inline bytevector ParsePubKey(const std::string &pubkeyhex) { @@ -164,6 +164,7 @@ void LogTx(const T& tx) std::clog << "\t\t" << in.prevout.hash.GetHex() << " : " << in.prevout.n << "\n" + << "\t\tnSequence: " << in.nSequence << "\n" << "\t\tWitness {\n"; for(const auto& wel: in.scriptWitness.stack) diff --git a/src/common/utils.hpp b/src/common/utils.hpp index 44cef39..e5f2ed6 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -33,47 +33,51 @@ uint32_t GetCsvInBlocks(uint32_t blocks); template void LogTx(const T& tx); -class IBech32Coder { +enum ChainType {BTC, L15}; +enum ChainMode {MAINNET, TESTNET, REGTEST}; -public: - enum ChainType {BTC, L15}; - enum ChainMode {MAINNET, TESTNET, REGTEST}; - - virtual ~IBech32Coder() = default; - std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const - { return Encode(pk.get_vector(), encoding); } - virtual std::string Encode(const bytevector& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const = 0; - virtual bytevector Decode(const std::string& address) const = 0; -}; - -template struct Hrp; -template <> struct Hrp { const static char* const value; }; -template <> struct Hrp { const static char* const value; }; -template <> struct Hrp { const static char* const value; }; -template <> struct Hrp { const static char* const value; }; -template <> struct Hrp { const static char* const value; }; -template <> struct Hrp { const static char* const value; }; +template struct Hrp; +template <> struct Hrp { const static char* const value; }; +template <> struct Hrp { const static char* const value; }; +template <> struct Hrp { const static char* const value; }; +template <> struct Hrp { const static char* const value; }; +template <> struct Hrp { const static char* const value; }; +template <> struct Hrp { const static char* const value; }; -template class Bech32Coder: public IBech32Coder +class Bech32Coder { + ChainType chaintype; + ChainMode chainmode; + const char* hrptag; public: - typedef Hrp hrp; - ~Bech32Coder() override = default; - using IBech32Coder::Encode; - std::string Encode(const bytevector& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const override { + Bech32Coder(ChainType c, ChainMode m) : chaintype(c), chainmode(m), + hrptag(chaintype == L15 + ? (m == MAINNET ? Hrp::value : (m == TESTNET ? Hrp::value : Hrp::value)) + : (m == MAINNET ? Hrp::value : (m == TESTNET ? Hrp::value : Hrp::value))) + {} + + Bech32Coder(const Bech32Coder& ) = default; + + std::string Encode(const bytevector& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const + { std::vector bech32buf = {(encoding == bech32::Encoding::BECH32) ? (uint8_t)0 : (uint8_t)1}; bech32buf.reserve(1 + ((pk.end() - pk.begin()) * 8 + 4) / 5); ConvertBits<8, 5, true>([&](unsigned char c) { bech32buf.push_back(c); }, pk.begin(), pk.end()); - return bech32::Encode(encoding, hrp::value, bech32buf); + return bech32::Encode(encoding, hrptag, bech32buf); } - bytevector Decode(const std::string& address) const override { + + std::string Encode(const xonly_pubkey& pk, bech32::Encoding encoding = bech32::Encoding::BECH32M) const + { return Encode(pk.get_vector(), encoding); } + + bytevector Decode(const std::string& address) const + { bech32::DecodeResult bech_result = bech32::Decode(address); - if(bech_result.hrp != hrp::value) + if(bech_result.hrp != hrptag) { - throw std::runtime_error(std::string("Address prefix should be ") + hrp::value + ". Address: " + address); + throw std::runtime_error(std::string("Address prefix should be ") + hrptag + ". Address: " + address); } if(bech_result.data.size() < 1) { diff --git a/src/core/transaction.cpp b/src/core/transaction.cpp index c11a571..b310c24 100644 --- a/src/core/transaction.cpp +++ b/src/core/transaction.cpp @@ -47,16 +47,13 @@ std::string GetTaprootPubKey(const CTxOut &out) std::string GetTaprootAddress(const std::string& chain_mode, const std::string& pubkey) { if (chain_mode == "testnet") { - Bech32Coder bech32; - return bech32.Encode(unhex(pubkey)); + return Bech32Coder(BTC, TESTNET).Encode(unhex(pubkey)); } else if (chain_mode == "mainnet") { - Bech32Coder bech32; - return bech32.Encode(unhex(pubkey)); + return Bech32Coder(BTC, MAINNET).Encode(unhex(pubkey)); } else if (chain_mode == "regtest") { - Bech32Coder bech32; - return bech32.Encode(unhex(pubkey)); + return Bech32Coder(BTC, REGTEST).Encode(unhex(pubkey)); } else { throw IllegalArgumentError(std::string(chain_mode)); @@ -71,16 +68,13 @@ std::string GetAddress(const std::string& chain_mode, const bytevector& pubkeysc bool segwit = script.IsWitnessProgram(witver, witnessprogram); if (segwit) { if (chain_mode == "testnet") { - Bech32Coder bech32; - return bech32.Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); + return Bech32Coder(BTC, TESTNET).Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); } else if (chain_mode == "mainnet") { - Bech32Coder bech32; - return bech32.Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); + return Bech32Coder(BTC, MAINNET).Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); } else if (chain_mode == "regtest") { - Bech32Coder bech32; - return bech32.Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); + return Bech32Coder(BTC, REGTEST).Encode(witnessprogram, witver == 0 ? bech32::Encoding::BECH32 : bech32::Encoding::BECH32M); } else { throw IllegalArgumentError(std::string(chain_mode)); diff --git a/src/tools/nodehelper.cpp b/src/tools/nodehelper.cpp index e13f477..c8c340e 100644 --- a/src/tools/nodehelper.cpp +++ b/src/tools/nodehelper.cpp @@ -7,24 +7,25 @@ namespace l15 { -void StartNode(ChainMode mode, ExecHelper& node_exec, const CLI::App& options) +void StartNode(NodeChainMode mode, ExecHelper& node_exec, const CLI::App& options) { node_exec.Arguments().clear(); node_exec.Arguments().emplace_back("-daemon"); - node_exec.Arguments().emplace_back("-daemonwait"); for(const auto opt: options.get_options([](const CLI::Option* o){ return o && !o->check_name("--help"); })) { std::clog << opt->get_name() << " == " << opt->as() << std::endl; node_exec.Arguments().emplace_back(opt->get_name() + "=" + opt->as()); } - if(mode == ChainMode::MODE_REGTEST) node_exec.Arguments().emplace_back("-regtest"); - else if(mode == ChainMode::MODE_TESTNET) node_exec.Arguments().emplace_back("-testnet"); + if(mode == NodeChainMode::MODE_REGTEST) node_exec.Arguments().emplace_back("-regtest"); + else if(mode == NodeChainMode::MODE_TESTNET) node_exec.Arguments().emplace_back("-testnet"); node_exec.Run(); + + std::this_thread::sleep_for(std::chrono::seconds(5)); } -void StopNode(ChainMode mode, ExecHelper& cli_exec, const CLI::App& options) +void StopNode(NodeChainMode mode, ExecHelper& cli_exec, const CLI::App& options) { cli_exec.Arguments().clear(); @@ -32,8 +33,8 @@ void StopNode(ChainMode mode, ExecHelper& cli_exec, const CLI::App& options) { cli_exec.Arguments().emplace_back(opt->get_name() + "=" + opt->as()); } - if(mode == ChainMode::MODE_REGTEST) cli_exec.Arguments().emplace_back("-regtest"); - else if(mode == ChainMode::MODE_TESTNET) cli_exec.Arguments().emplace_back("-testnet"); + if(mode == NodeChainMode::MODE_REGTEST) cli_exec.Arguments().emplace_back("-regtest"); + else if(mode == NodeChainMode::MODE_TESTNET) cli_exec.Arguments().emplace_back("-testnet"); cli_exec.Arguments().emplace_back("stop"); diff --git a/src/tools/nodehelper.hpp b/src/tools/nodehelper.hpp index 2f173b1..ad2601c 100644 --- a/src/tools/nodehelper.hpp +++ b/src/tools/nodehelper.hpp @@ -10,11 +10,11 @@ class App; namespace l15 { - enum class ChainMode {MODE_MAINNET, MODE_TESTNET, MODE_REGTEST}; + enum class NodeChainMode {MODE_MAINNET, MODE_TESTNET, MODE_REGTEST}; class ExecHelper; - void StartNode(ChainMode mode, ExecHelper& node_exec, const CLI::App& options); - void StopNode(ChainMode mode, ExecHelper& cli_exec, const CLI::App& options); + void StartNode(NodeChainMode mode, ExecHelper& node_exec, const CLI::App& options); + void StopNode(NodeChainMode mode, ExecHelper& cli_exec, const CLI::App& options); } \ No newline at end of file diff --git a/test/core/test_derive_key.cpp b/test/core/test_derive_key.cpp index 8c4651c..6719427 100644 --- a/test/core/test_derive_key.cpp +++ b/test/core/test_derive_key.cpp @@ -17,7 +17,7 @@ const std::function G_TRANSLATION_FUN = nullptr; static const bytevector seed = unhex( "b37f263befa23efb352f0ba45a5e452363963fabc64c946a75df155244630ebaa1ac8056b873e79232486d5dd36809f8925c9c5ac8322f5380940badc64cc6fe"); -static const auto bech = Bech32Coder(); +static const auto bech = Bech32Coder(BTC, TESTNET); static const std::vector derive_branches = { MasterKey::BIP86_TAPROOT | MasterKey::BIP32_HARDENED_KEY_LIMIT, diff --git a/test/test_case_wrapper.hpp b/test/test_case_wrapper.hpp index 6be08ae..2d26833 100644 --- a/test/test_case_wrapper.hpp +++ b/test/test_case_wrapper.hpp @@ -35,28 +35,19 @@ struct TestcaseWrapper core::ChainApi mBtc; ExecHelper mCli; ExecHelper mBtcd; - std::unique_ptr mBech; + Bech32Coder mBech; explicit TestcaseWrapper(const std::string& configpath, const std::string& clipath) : mConfFactory(configpath), mMode(mConfFactory.conf[config::option::CHAINMODE].as()), mBtc(std::move(mConfFactory.conf.ChainValues(config::BITCOIN)), clipath), mCli(clipath, false), - mBtcd("bitcoind", false) + mBtcd("bitcoind", false), + mBech(mMode == "mainnet" ? Bech32Coder(BTC, MAINNET) : + (mMode == "testnet" ? + Bech32Coder(BTC, TESTNET) : + Bech32Coder(BTC, REGTEST))) { - if (mMode == "regtest") { - mBech.reset(new Bech32Coder()); - } - else if (mMode == "testnet") { - mBech.reset(new Bech32Coder()); - } - else if (mMode == "mainnet") { - mBech.reset(new Bech32Coder()); - } - else { - throw std::runtime_error("Wrong chain mode"); - } - bool is_connected = true; try { btc().CheckConnection(); @@ -95,12 +86,12 @@ struct TestcaseWrapper void StartRegtestBitcoinNode() { - StartNode(ChainMode::MODE_REGTEST, mBtcd, conf().Subcommand(config::BITCOIND)); + StartNode(NodeChainMode::MODE_REGTEST, mBtcd, conf().Subcommand(config::BITCOIND)); } void StopRegtestBitcoinNode() { - StopNode(ChainMode::MODE_REGTEST, mCli, conf().Subcommand(config::BITCOIN)); + StopNode(NodeChainMode::MODE_REGTEST, mCli, conf().Subcommand(config::BITCOIN)); } Config& conf() @@ -109,8 +100,8 @@ struct TestcaseWrapper core::ChainApi& btc() { return mBtc; } - IBech32Coder& bech32() const - { return *mBech; } + const Bech32Coder& bech32() const + { return mBech; } void ResetRegtestMemPool() { From 4b86b8b1902b04079a42ac00066ae0f7a5caad0e Mon Sep 17 00:00:00 2001 From: l2xl Date: Sat, 8 Jun 2024 01:23:48 +0300 Subject: [PATCH 30/59] Refactor ECC keys infrastructure --- configure.ac | 3 +- contrib/nlohmann_json/LICENSE | 17 + contrib/nlohmann_json/nlohmann/json.hpp | 24659 ++++++++++++++++++ contrib/nlohmann_json/nlohmann/json_fwd.hpp | 176 + src/api/signer_api.hpp | 2 +- src/api/wallet_api.cpp | 6 +- src/api/wallet_api.hpp | 4 +- src/common/utils.cpp | 8 - src/common/utils.hpp | 54 +- src/core/Makefile.am | 11 +- src/core/channel.hpp | 2 +- src/core/channel_keys.hpp | 84 - src/core/ecdsa.cpp | 77 + src/core/ecdsa.hpp | 36 + src/core/keypair.hpp | 48 + src/core/keyregistry.cpp | 321 + src/core/keyregistry.hpp | 100 + src/core/master_key.cpp | 10 +- src/core/master_key.hpp | 8 +- src/core/{channel_keys.cpp => schnorr.cpp} | 37 +- src/core/schnorr.hpp | 61 + src/core/transaction.cpp | 12 +- test/core/Makefile.am | 5 +- test/core/test_derive_key.cpp | 22 +- test/core/test_node.cpp | 6 +- test/core/test_signing.cpp | 292 + test/core/test_suite_channel.hpp | 2 +- test/core/test_taproot.cpp | 26 +- test/core/test_taptree.cpp | 11 +- test/service/test_onchain_service.cpp | 2 +- test/signer.cpp | 6 +- test/test_case_wrapper.hpp | 12 +- 32 files changed, 25919 insertions(+), 201 deletions(-) create mode 100644 contrib/nlohmann_json/LICENSE create mode 100644 contrib/nlohmann_json/nlohmann/json.hpp create mode 100644 contrib/nlohmann_json/nlohmann/json_fwd.hpp delete mode 100644 src/core/channel_keys.hpp create mode 100644 src/core/ecdsa.cpp create mode 100644 src/core/ecdsa.hpp create mode 100644 src/core/keypair.hpp create mode 100644 src/core/keyregistry.cpp create mode 100644 src/core/keyregistry.hpp rename src/core/{channel_keys.cpp => schnorr.cpp} (87%) create mode 100644 src/core/schnorr.hpp create mode 100644 test/core/test_signing.cpp diff --git a/configure.ac b/configure.ac index cd2ae2f..95de9a1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.69]) AC_INIT([L15 Core], [m4_esyscmd_s([./version.sh])], [l2xl@protonmail.com]) -AC_CONFIG_SRCDIR([src/core/channel_keys.cpp]) +AC_CONFIG_SRCDIR([src/core/schnorr.cpp]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([build-aux/m4]) @@ -151,6 +151,7 @@ AM_CONDITIONAL([BUILD_TOOLS], [test "$enable_build_tools" = "yes"]) AM_CONDITIONAL([BUILD_PLUGIN_API], [test "$enable_plugin_api" = "yes"]) AM_CONDITIONAL([BUILD_SECP256K1], [test "$with_secp256k1" != "node"]) AM_CONDITIONAL([BUILD_FROST], [test "$enable_build_frost_signer" = "yes"]) +AM_CONDITIONAL([WASM], [test "$with_emscripten" = "yes"]) dnl Enable debug diff --git a/contrib/nlohmann_json/LICENSE b/contrib/nlohmann_json/LICENSE new file mode 100644 index 0000000..719b935 --- /dev/null +++ b/contrib/nlohmann_json/LICENSE @@ -0,0 +1,17 @@ +The class is licensed under the MIT License: + +Copyright © 2013-2022 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +The class contains the UTF-8 Decoder from Bjoern Hoehrmann which is licensed under the MIT License (see above). Copyright © 2008-2009 Björn Hoehrmann bjoern@hoehrmann.de + +The class contains a slightly modified version of the Grisu2 algorithm from Florian Loitsch which is licensed under the MIT License (see above). Copyright © 2009 Florian Loitsch + +The class contains a copy of Hedley from Evan Nemerson which is licensed as CC0-1.0. + +The class contains parts of Google Abseil which is licensed under the Apache 2.0 License. \ No newline at end of file diff --git a/contrib/nlohmann_json/nlohmann/json.hpp b/contrib/nlohmann_json/nlohmann/json.hpp new file mode 100644 index 0000000..8aa757c --- /dev/null +++ b/contrib/nlohmann_json/nlohmann/json.hpp @@ -0,0 +1,24659 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +// See LICENSE file for details about the license + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +// #include + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.2 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template