diff --git a/.gitignore b/.gitignore index 2269cba124..d2aa17b418 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,12 @@ build *.tmp .DS_Store +# Codegen +libain_rpc.cpp +libain_rpc.h +libmc.cpp +libmc.h + # Build directory. build/ out/ diff --git a/.python-version b/.python-version deleted file mode 100644 index c49282585a..0000000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.5.6 diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index ae2a98c683..2c4cd411a4 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -27,7 +27,7 @@ export BASE_BUILD_DIR=${BASE_BUILD_DIR:-${TRAVIS_BUILD_DIR:-$BASE_ROOT_DIR}} export BASE_OUTDIR=${BASE_OUTDIR:-$BASE_BUILD_DIR/out/$HOST} export SDK_URL=${SDK_URL:-https://bitcoincore.org/depends-sources/sdks} export WINEDEBUG=${WINEDEBUG:-fixme-all} -export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3} +export DOCKER_PACKAGES=${DOCKER_PACKAGES:-build-essential libtool autotools-dev automake pkg-config bsdmainutils curl ca-certificates ccache python3 git unzip} export GOAL=${GOAL:-install} export DIR_QA_ASSETS=${DIR_QA_ASSETS:-${BASE_BUILD_DIR}/qa-assets} export PATH=${BASE_ROOT_DIR}/ci/retry:$PATH diff --git a/ci/test/04_install.sh b/ci/test/04_install.sh index c77f1a416e..fdcabdb5b5 100755 --- a/ci/test/04_install.sh +++ b/ci/test/04_install.sh @@ -49,3 +49,15 @@ DOCKER_EXEC echo "Number of CPUs \(nproc\): $(nproc)" ${CI_RETRY_EXE} DOCKER_EXEC apt-get update ${CI_RETRY_EXE} DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES +# Install Rust toolchain +DOCKER_EXEC "curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y" +DOCKER_EXEC ln -s /root/.cargo/bin/cargo /usr/bin/cargo +DOCKER_EXEC ln -s /root/.cargo/bin/rustc /usr/bin/rustc +DOCKER_EXEC ln -s /root/.cargo/bin/rustup /usr/bin/rustup +DOCKER_EXEC rustup target add x86_64-unknown-linux-gnu + +DOCKER_EXEC "curl -L https://github.com/protocolbuffers/protobuf/releases/download/v3.20.0/protoc-3.20.0-linux-x86_64.zip -o /tmp/proto.zip" +DOCKER_EXEC "unzip -o /tmp/proto.zip -d /tmp/proto" +DOCKER_EXEC "chmod 755 -R /tmp/proto/bin" +DOCKER_EXEC "cp /tmp/proto/bin/protoc /usr/local/bin/" +DOCKER_EXEC "cp -R /tmp/proto/include/* /usr/local/include/" diff --git a/ci/test/05_before_script.sh b/ci/test/05_before_script.sh index 7b97902919..9b2e3e0a05 100755 --- a/ci/test/05_before_script.sh +++ b/ci/test/05_before_script.sh @@ -25,3 +25,5 @@ fi if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC CONFIG_SHELL= make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS fi + +TARGET=${HOST} ./make.sh patch_codegen diff --git a/configure.ac b/configure.ac index bada465987..df191f5d06 100644 --- a/configure.ac +++ b/configure.ac @@ -504,6 +504,8 @@ case $host in AC_CHECK_LIB([shlwapi], [main],, AC_MSG_ERROR(libshlwapi missing)) AC_CHECK_LIB([iphlpapi], [main],, AC_MSG_ERROR(libiphlpapi missing)) AC_CHECK_LIB([crypt32], [main],, AC_MSG_ERROR(libcrypt32 missing)) + AC_CHECK_LIB([bcrypt], [main],, AC_MSG_ERROR(libbcrypt missing)) + AC_CHECK_LIB([userenv], [main],, AC_MSG_ERROR(libuserenv missing)) # -static is interpreted by libtool, where it has a different meaning. # In libtool-speak, it's -all-static. @@ -620,6 +622,9 @@ case $host in ;; esac +AC_CHECK_LIB([ain_grpc],[main],AIN_GRPC_LIBS=-lain_grpc,AC_MSG_ERROR(libain_grpc missing)) +AC_CHECK_LIB([metachain],[main],METACHAIN_LIBS=-lmetachain,AC_MSG_ERROR(libmetachain missing)) + if test x$use_pkgconfig = xyes; then m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)]) m4_ifdef([PKG_PROG_PKG_CONFIG], [ @@ -1417,7 +1422,9 @@ fi AM_CONDITIONAL([TARGET_DARWIN], [test x$TARGET_OS = xdarwin]) AM_CONDITIONAL([BUILD_DARWIN], [test x$BUILD_OS = xdarwin]) +AM_CONDITIONAL([BUILD_NOT_DARWIN], [test x$BUILD_OS != xdarwin]) AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows]) +AM_CONDITIONAL([TARGET_NOT_WINDOWS], [test x$TARGET_OS != xwindows]) AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes]) AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes]) AM_CONDITIONAL([ENABLE_FUZZ],[test x$enable_fuzz = xyes]) @@ -1487,6 +1494,8 @@ AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) +AC_SUBST(AIN_GRPC_LIBS) +AC_SUBST(METACHAIN_LIBS) AC_SUBST(ZMQ_LIBS) AC_SUBST(QR_LIBS) AC_SUBST(HAVE_GMTIME_R) diff --git a/contrib/dockerfiles/x86_64-apple-darwin18.dockerfile b/contrib/dockerfiles/x86_64-apple-darwin18.dockerfile index 7eddef9775..b22253366c 100644 --- a/contrib/dockerfiles/x86_64-apple-darwin18.dockerfile +++ b/contrib/dockerfiles/x86_64-apple-darwin18.dockerfile @@ -14,10 +14,22 @@ RUN apt update && apt dist-upgrade -y RUN apt install -y software-properties-common build-essential git libtool autotools-dev automake \ pkg-config bsdmainutils python3 libssl-dev libevent-dev libboost-system-dev \ libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev \ -libminiupnpc-dev libzmq3-dev libqrencode-dev \ -curl cmake \ +libminiupnpc-dev libzmq3-dev libqrencode-dev curl cmake unzip \ python3-dev python3-pip libcap-dev libbz2-dev libz-dev fonts-tuffy librsvg2-bin libtiff-tools imagemagick +# install protobuf +RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.20.0/protoc-3.20.0-linux-x86_64.zip +RUN unzip -o protoc-3.20.0-linux-x86_64.zip -d ./proto +RUN chmod 755 -R ./proto/bin +RUN cp ./proto/bin/protoc /usr/local/bin/ +RUN cp -R ./proto/include/* /usr/local/include/ + +# install rustlang +RUN curl https://sh.rustup.rs -sSf | \ + sh -s -- --default-toolchain stable -y +ENV PATH=/root/.cargo/bin:$PATH +RUN rustup target add x86_64-apple-darwin + # For Berkeley DB - but we don't need as we do a depends build. # RUN apt install -y libdb-dev @@ -43,6 +55,7 @@ WORKDIR /work COPY --from=depends-builder /work/depends ./depends COPY . . +RUN ./make.sh patch_codegen ${TARGET} RUN ./autogen.sh # XREF: #make-configure diff --git a/contrib/dockerfiles/x86_64-pc-linux-gnu.dockerfile b/contrib/dockerfiles/x86_64-pc-linux-gnu.dockerfile index 780db7d5ee..f71fa95b73 100644 --- a/contrib/dockerfiles/x86_64-pc-linux-gnu.dockerfile +++ b/contrib/dockerfiles/x86_64-pc-linux-gnu.dockerfile @@ -12,6 +12,19 @@ COPY ./make.sh . RUN apt update && apt install -y apt-transport-https RUN export DEBIAN_FRONTEND=noninteractive && ./make.sh pkg-install-deps-x86_64 +# install protobuf +RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.20.0/protoc-3.20.0-linux-x86_64.zip +RUN unzip -o protoc-3.20.0-linux-x86_64.zip -d ./proto +RUN chmod 755 -R ./proto/bin +RUN cp ./proto/bin/protoc /usr/local/bin/ +RUN cp -R ./proto/include/* /usr/local/include/ + +# install rustlang +RUN curl https://sh.rustup.rs -sSf | \ + sh -s -- --default-toolchain stable -y +ENV PATH=/root/.cargo/bin:$PATH +RUN rustup target add x86_64-unknown-linux-gnu + # ----------- FROM builder-base as depends-builder ARG TARGET @@ -36,7 +49,7 @@ WORKDIR /work COPY . . RUN ./make.sh purge && rm -rf ./depends COPY --from=depends-builder /work/depends ./depends - +RUN ./make.sh patch_codegen ${TARGET} RUN export MAKE_COMPILER="CC=gcc CXX=g++" && \ ./make.sh build-conf && ./make.sh build-make diff --git a/contrib/dockerfiles/x86_64-w64-mingw32.dockerfile b/contrib/dockerfiles/x86_64-w64-mingw32.dockerfile index 165a74e3cb..0615668c80 100644 --- a/contrib/dockerfiles/x86_64-w64-mingw32.dockerfile +++ b/contrib/dockerfiles/x86_64-w64-mingw32.dockerfile @@ -14,10 +14,26 @@ RUN apt update && apt dist-upgrade -y RUN apt install -y software-properties-common build-essential git libtool autotools-dev automake \ pkg-config bsdmainutils python3 libssl-dev libevent-dev libboost-system-dev \ libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev \ -libminiupnpc-dev libzmq3-dev libqrencode-dev \ -curl cmake \ +libminiupnpc-dev libzmq3-dev libqrencode-dev curl cmake unzip \ g++-mingw-w64-x86-64 mingw-w64-x86-64-dev nsis +# install protobuf +RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.20.0/protoc-3.20.0-linux-x86_64.zip +RUN unzip -o protoc-3.20.0-linux-x86_64.zip -d ./proto +RUN chmod 755 -R ./proto/bin +RUN cp ./proto/bin/protoc /usr/local/bin/ +RUN cp -R ./proto/include/* /usr/local/include/ + +# install rustlang +RUN curl https://sh.rustup.rs -sSf | \ + sh -s -- --default-toolchain stable -y +ENV PATH=/root/.cargo/bin:$PATH +RUN rustup target add x86_64-pc-windows-gnu +RUN printf '\n\ + [target.x86_64-pc-windows-gnu]\n\ + linker = "x86_64-w64-mingw32-gcc"\n\ + ar = "x86_64-w64-mingw32-ar"\n' > /root/.cargo/config + # Set the default mingw32 g++ compiler option to posix. RUN update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix diff --git a/depends/Makefile b/depends/Makefile index 9ef38551e5..ca4bddecd6 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -96,7 +96,7 @@ zmq_packages_$(NO_ZMQ) = $(zmq_packages) rapidcheck_packages_$(RAPIDCHECK) = $(rapidcheck_packages) -packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(wallet_packages_) $(upnp_packages_) +packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(wallet_packages_) $(upnp_packages_) $(libmc_packages) $(libain_packages) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) ifneq ($(zmq_packages_),) diff --git a/depends/packages/libain.mk b/depends/packages/libain.mk new file mode 100644 index 0000000000..c22cda0863 --- /dev/null +++ b/depends/packages/libain.mk @@ -0,0 +1,41 @@ +package=libain +$(package)_version=master +$(package)_git_path=https://github.com/DeFiCh/libain-rs + +define $(package)_fetch_cmds + if [ ! -z ${LIBAIN_PATH} ]; then \ + echo "Using local path for libain-rs"; \ + mkdir -p $$(base_build_dir)/$$(host)/$(package); \ + ln -s $(LIBAIN_PATH) $$($(package)_extract_dir); \ + else \ + echo "Cloning from Git repository for libain-rs"; \ + git clone --single-branch --branch master $$($(package)_git_path) $$($(package)_extract_dir); \ + fi +endef + +define $(package)_extract_cmds +echo "Skipping extraction for libain source" +endef + +# Perform target substitutions for Rust +LIBAIN_TARGET := $(HOST) +ifeq ($(LIBAIN_TARGET),x86_64-pc-linux-gnu) + LIBAIN_TARGET=x86_64-unknown-linux-gnu +endif +ifeq ($(LIBAIN_TARGET),arm-linux-gnueabihf) + LIBAIN_TARGET=arm-unknown-linux-gnueabihf +endif +ifeq ($(LIBAIN_TARGET),x86_64-apple-darwin18) + LIBAIN_TARGET=aarch64-apple-darwin +endif +ifeq ($(LIBAIN_TARGET),x86_64-w64-mingw32) + LIBAIN_TARGET=x86_64-pc-windows-gnu +endif + +define $(package)_build_cmds + $(MAKE) build-grpc-pkg TARGET=$(LIBAIN_TARGET) +endef + +define $(package)_stage_cmds + cp -r pkg/ain-grpc/* $($(package)_staging_dir)$(host_prefix)/ +endef diff --git a/depends/packages/libmc.mk b/depends/packages/libmc.mk new file mode 100644 index 0000000000..49064ba451 --- /dev/null +++ b/depends/packages/libmc.mk @@ -0,0 +1,41 @@ +package=libmc +$(package)_version=master +$(package)_git_path=https://github.com/DeFiCh/metachain + +define $(package)_fetch_cmds + if [ ! -z ${LIBMC_PATH} ]; then \ + echo "Using local path for metachain"; \ + mkdir -p $$(base_build_dir)/$$(host)/$(package); \ + ln -s $(LIBMC_PATH) $$($(package)_extract_dir); \ + else \ + echo "Cloning from Git repository for metachain"; \ + git clone --single-branch --branch libmc $$($(package)_git_path) $$($(package)_extract_dir); \ + fi +endef + +define $(package)_extract_cmds +echo "Skipping extraction for metachain source" +endef + +# Perform target substitutions for Rust +LIBMC_TARGET := $(HOST) +ifeq ($(LIBMC_TARGET),x86_64-pc-linux-gnu) + LIBMC_TARGET=x86_64-unknown-linux-gnu +endif +ifeq ($(LIBMC_TARGET),arm-linux-gnueabihf) + LIBMC_TARGET=arm-unknown-linux-gnueabihf +endif +ifeq ($(LIBMC_TARGET),x86_64-apple-darwin18) + LIBMC_TARGET=aarch64-apple-darwin +endif +ifeq ($(LIBMC_TARGET),x86_64-w64-mingw32) + LIBMC_TARGET=x86_64-pc-windows-gnu +endif + +define $(package)_build_cmds + $(MAKE) build-native-pkg TARGET=$(LIBMC_TARGET) +endef + +define $(package)_stage_cmds + cp -r pkg/metachain/* $($(package)_staging_dir)$(host_prefix)/ +endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index ea003be486..914047a86e 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -8,6 +8,10 @@ zmq_packages=zeromq upnp_packages=miniupnpc +libain_packages = libain + +libmc_packages = libmc + darwin_native_packages = native_biplist native_ds_store native_mac_alias ifneq ($(build_os),darwin) diff --git a/make.sh b/make.sh index a144ad8013..ea162c2417 100755 --- a/make.sh +++ b/make.sh @@ -112,6 +112,21 @@ build_deps() { popd >/dev/null } +patch_codegen() { + local target=${1:-${TARGET}} + # Required for patching C++ glue emitted from Rust build + printf "#ifndef DEFI_RUST_RPC_H\n#define DEFI_RUST_RPC_H\n\n" > "$(pwd)/src/libain_rpc.h" + cat "$(pwd)/depends/${target}/include/libain_rpc.hpp" >> "$(pwd)/src/libain_rpc.h" + printf "\n#endif // DEFI_RUST_RPC_H" >> "$(pwd)/src/libain_rpc.h" + printf "#include \n" > "$(pwd)/src/libain_rpc.cpp" + cat "$(pwd)/depends/${target}/libain_rpc.cpp" >> "$(pwd)/src/libain_rpc.cpp" + printf "#ifndef DEFI_METACHAIN_H\n#define DEFI_METACHAIN_H\n\n" > "$(pwd)/src/libmc.h" + cat "$(pwd)/depends/${target}/include/libmc.hpp" >> "$(pwd)/src/libmc.h" + printf "\n#endif // DEFI_METACHAIN_H" >> "$(pwd)/src/libmc.h" + printf "#include \n" > "$(pwd)/src/libmc.cpp" + cat "$(pwd)/depends/${target}/libmc.cpp" >> "$(pwd)/src/libmc.cpp" +} + build_conf() { local target=${1:-${TARGET}} local make_conf_opts=${MAKE_CONF_ARGS:-} @@ -138,6 +153,7 @@ build_make() { build() { build_deps "$@" + patch_codegen "$@" build_conf "$@" build_make "$@" } @@ -389,7 +405,7 @@ pkg_install_deps_x86_64() { libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev \ libminiupnpc-dev libzmq3-dev libqrencode-dev wget \ libdb-dev libdb++-dev libdb5.3 libdb5.3-dev libdb5.3++ libdb5.3++-dev \ - curl cmake + curl cmake unzip } pkg_install_llvm() { diff --git a/src/Makefile.am b/src/Makefile.am index 117432665f..bc5d2301c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -372,6 +372,12 @@ libdefi_server_a_SOURCES = \ index/txindex.cpp \ interfaces/chain.cpp \ init.cpp \ + libain_rpc.h \ + libain_rpc.cpp \ + libmc.h \ + libmc.cpp \ + dmc_handler.h \ + dmc_handler.cpp \ dbwrapper.cpp \ masternodes/accounts.cpp \ masternodes/accountshistory.cpp \ @@ -672,9 +678,20 @@ nodist_libdefi_util_a_SOURCES = $(srcdir)/obj/build.h defid_SOURCES = defid.cpp defid_CPPFLAGS = $(AM_CPPFLAGS) $(DEFI_INCLUDES) defid_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) +# FIXME(wafflespeanut): Allowing multiple definitions because symbols conflict across Rust static libs defid_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +if TARGET_DARWIN +defid_LDFLAGS += -framework Security -framework SystemConfiguration -framework CoreFoundation +endif +if BUILD_NOT_DARWIN +defid_LDFLAGS += -Wl,--allow-multiple-definition +endif +if TARGET_NOT_WINDOWS +defid_LDFLAGS += -lain_grpc -lmetachain -ldl +endif if TARGET_WINDOWS +defid_LDFLAGS += -luserenv -lbcrypt defid_SOURCES += defid-res.rc endif @@ -683,7 +700,6 @@ endif defid_LDADD = \ $(LIBDEFI_SERVER) \ $(LIBDEFI_WALLET) \ - $(LIBDEFI_SERVER) \ $(LIBDEFI_COMMON) \ $(LIBUNIVALUE) \ $(LIBDEFI_SPV) \ @@ -695,7 +711,7 @@ defid_LDADD = \ $(LIBMEMENV) \ $(LIBSECP256K1) -defid_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) +defid_LDADD +=$(AIN_GRPC_LIBS) $(METACHAIN_LIBS) $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # defi-cli binary # defi_cli_SOURCES = defi-cli.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 31107f51c8..862a99ad94 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -74,8 +74,20 @@ bench_bench_defi_SOURCES += bench/coin_selection.cpp bench_bench_defi_SOURCES += bench/wallet_balance.cpp endif -bench_bench_defi_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) +bench_bench_defi_LDADD += $(AIN_GRPC_LIBS) $(METACHAIN_LIBS) $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) bench_bench_defi_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +if TARGET_DARWIN +bench_bench_defi_LDFLAGS += -framework Security -framework SystemConfiguration -framework CoreFoundation +endif +if BUILD_NOT_DARWIN +bench_bench_defi_LDFLAGS += -Wl,--allow-multiple-definition +endif +if TARGET_NOT_WINDOWS +bench_bench_defi_LDFLAGS += -lain_grpc -lmetachain -ldl +endif +if TARGET_WINDOWS +bench_bench_defi_LDFLAGS += -luserenv -lbcrypt +endif CLEAN_DEFI_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 1b254abbe1..8a8862efdd 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -195,8 +195,20 @@ test_test_defi_LDADD += $(LIBDEFI_SERVER) $(LIBDEFI_CLI) $(LIBDEFI_COMMON) $(LIB $(LIBDEFI_SPV) $(LIBLEVELDB) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) test_test_defi_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_defi_LDADD += $(BDB_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS) +test_test_defi_LDADD += $(AIN_GRPC_LIBS) $(METACHAIN_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS) test_test_defi_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static +if TARGET_DARWIN +test_test_defi_LDFLAGS += -framework Security -framework SystemConfiguration -framework CoreFoundation +endif +if BUILD_NOT_DARWIN +test_test_defi_LDFLAGS += -Wl,--allow-multiple-definition +endif +if TARGET_NOT_WINDOWS +test_test_defi_LDFLAGS += -lain_grpc -lmetachain -ldl +endif +if TARGET_WINDOWS +test_test_defi_LDFLAGS += -luserenv -lbcrypt +endif if ENABLE_ZMQ test_test_defi_LDADD += $(LIBDEFI_ZMQ) $(ZMQ_LIBS) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 985cb294b0..4c6e893e3c 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -139,6 +139,7 @@ class CMainParams : public CChainParams { consensus.FortCanningGreatWorldHeight = 2212000; // Sep 7th, 2022. consensus.FortCanningEpilogueHeight = 2257500; // Sep 22nd, 2022. consensus.GrandCentralHeight = 2479000; // Dec 8th, 2022. + consensus.DMCGenesisHeight = std::numeric_limits::max(); consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks @@ -293,6 +294,7 @@ class CMainParams : public CChainParams { consensus.burnAddress = GetScriptForDestination(DecodeDestination("8defichainBurnAddressXXXXXXXdRQkSm", *this)); consensus.retiredBurnAddress = GetScriptForDestination(DecodeDestination("8defichainDSTBurnAddressXXXXaCAuTq", *this)); + consensus.lockAddress = GetScriptForDestination(DecodeDestination("TODO: DECIDE ON ADDRESS>", *this)); // Destination for unused emission consensus.unusedEmission = GetScriptForDestination(DecodeDestination("df1qlwvtdrh4a4zln3k56rqnx8chu8t0sqx36syaea", *this)); @@ -394,6 +396,7 @@ class CTestNetParams : public CChainParams { consensus.FortCanningGreatWorldHeight = 1223000; consensus.FortCanningEpilogueHeight = 1244000; consensus.GrandCentralHeight = 1366000; + consensus.DMCGenesisHeight = std::numeric_limits::max(); consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks @@ -528,6 +531,7 @@ class CTestNetParams : public CChainParams { consensus.burnAddress = GetScriptForDestination(DecodeDestination("7DefichainBurnAddressXXXXXXXdMUE5n", *this)); consensus.retiredBurnAddress = GetScriptForDestination(DecodeDestination("7DefichainDSTBurnAddressXXXXXzS4Hi", *this)); + consensus.lockAddress = GetScriptForDestination(DecodeDestination("TODO: DECIDE ON ADDRESS>", *this)); // Destination for unused emission consensus.unusedEmission = GetScriptForDestination(DecodeDestination("7HYC4WVAjJ5BGVobwbGTEzWJU8tzY3Kcjq", *this)); @@ -605,6 +609,7 @@ class CDevNetParams : public CChainParams { consensus.FortCanningGreatWorldHeight = std::numeric_limits::max(); consensus.FortCanningEpilogueHeight = std::numeric_limits::max(); consensus.GrandCentralHeight = std::numeric_limits::max(); + consensus.DMCGenesisHeight = std::numeric_limits::max(); consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks @@ -733,6 +738,7 @@ class CDevNetParams : public CChainParams { consensus.burnAddress = GetScriptForDestination(DecodeDestination("7DefichainBurnAddressXXXXXXXdMUE5n", *this)); consensus.retiredBurnAddress = GetScriptForDestination(DecodeDestination("7DefichainDSTBurnAddressXXXXXzS4Hi", *this)); + consensus.lockAddress = GetScriptForDestination(DecodeDestination("TODO: DECIDE ON ADDRESS>", *this)); // Destination for unused emission consensus.unusedEmission = GetScriptForDestination(DecodeDestination("7HYC4WVAjJ5BGVobwbGTEzWJU8tzY3Kcjq", *this)); @@ -807,6 +813,7 @@ class CRegTestParams : public CChainParams { consensus.FortCanningGreatWorldHeight = 10000000; consensus.FortCanningEpilogueHeight = 10000000; consensus.GrandCentralHeight = 10000000; + consensus.DMCGenesisHeight = 10000000; consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks @@ -942,6 +949,7 @@ class CRegTestParams : public CChainParams { // For testing send after Eunos: 93ViFmLeJVgKSPxWGQHmSdT5RbeGDtGW4bsiwQM2qnQyucChMqQ consensus.burnAddress = GetScriptForDestination(DecodeDestination("mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG", *this)); consensus.retiredBurnAddress = GetScriptForDestination(DecodeDestination("mfdefichainDSTBurnAddressXXXZcE1vs", *this)); + consensus.lockAddress = GetScriptForDestination(DecodeDestination("2N9HiV9k2smL1953raxC4PxqN6kmN28c53D", *this)); // Destination for unused emission consensus.unusedEmission = GetScriptForDestination(DecodeDestination("mkzZWPwBVgdnwLSmXKW5SuUFMpm6C5ZPcJ", *this)); // cUUj4d9tkgJGwGBF7VwFvCpcFMuEpC8tYbduaCDexKMx8A8ntL7C @@ -1048,6 +1056,7 @@ void SetupCommonArgActivationParams(Consensus::Params &consensus) { UpdateHeightValidation("Fort Canning Great World", "-greatworldheight", consensus.FortCanningGreatWorldHeight); UpdateHeightValidation("Fort Canning Epilogue", "-fortcanningepilogueheight", consensus.FortCanningEpilogueHeight); UpdateHeightValidation("Grand Central", "-grandcentralheight", consensus.GrandCentralHeight); + UpdateHeightValidation("DMC Genesis", "-dmcgenesisheight", consensus.DMCGenesisHeight); if (gArgs.GetBoolArg("-simulatemainnet", false)) { consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks diff --git a/src/consensus/params.h b/src/consensus/params.h index f97a2eafa4..e54f55a9bc 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -100,6 +100,7 @@ struct Params { int FortCanningGreatWorldHeight; int FortCanningEpilogueHeight; int GrandCentralHeight; + int DMCGenesisHeight; /** Foundation share after AMK, normalized to COIN = 100% */ CAmount foundationShareDFIP1; @@ -109,6 +110,8 @@ struct Params { CScript retiredBurnAddress; /** Address to hold unused emission */ CScript unusedEmission; + /** Address for locking assets for Metachain bridge */ + CScript lockAddress; /** Struct to hold percentages for coinbase distribution. * Percentages are calculated out of 10000 */ diff --git a/src/defid.cpp b/src/defid.cpp index c6931ebb4d..f21489c056 100644 --- a/src/defid.cpp +++ b/src/defid.cpp @@ -10,9 +10,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -64,12 +66,23 @@ static bool AppInit(int argc, char* argv[]) bool fRet = false; util::ThreadRename("init"); + init_runtime(); // // Parameters // // If Qt is used, parameters/defi.conf are parsed in qt/defi.cpp's main() SetupServerArgs(); + bool isMetaEmbedded = false; + auto mcRes = InitMetachain(&argc, argv, isMetaEmbedded); + if (isMetaEmbedded) { + if (mcRes.is_help || !mcRes.daemon) { + return true; + } + if (!mcRes.success) { + return InitError("Failed to initialize metachain\n"); + } + } std::string error; if (!gArgs.ParseParameters(argc, argv, error)) { return InitError(strprintf("Error parsing command line arguments: %s\n", error)); @@ -93,8 +106,14 @@ static bool AppInit(int argc, char* argv[]) return true; } + bool hasRpc; try { + hasRpc = SetupMetachainHandler(); + if (!isMetaEmbedded && !hasRpc) { + return InitError("Expected one of '-meta' or '-meta_rpc' parameters to initialize metachain"); + } + if (!CheckDataDirOption()) { return InitError(strprintf("Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", ""))); } @@ -176,6 +195,14 @@ static bool AppInit(int argc, char* argv[]) WaitForShutdown(); } Shutdown(interfaces); + if (!hasRpc) { // send signal only if we use embedded node + try { + interrupt_dmc(); + } catch (const std::exception& e) { + PrintExceptionContinue(&e, "interrupt_dmc"); + } + } + stop_runtime(); return fRet; } diff --git a/src/dmc_handler.cpp b/src/dmc_handler.cpp new file mode 100644 index 0000000000..70ed0ea5b9 --- /dev/null +++ b/src/dmc_handler.cpp @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +std::string rpc_url; +bool is_ffi = true; // FIXME: Set this to `false` if both -meta and -meta_rpc is missing + + +bool SetupMetachainHandler() { + auto url = gArgs.GetArg("-meta_rpc", ""); + if (!url.empty()) { + // Test the instantiation of client for this URL. Calling this multiple + // times wouldn't hurt because it's a singleton for each URL in libain + NewClient(url); + rpc_url = url; + is_ffi = false; + } + + return !url.empty(); +} + +Res MintDmcBlock(CBlock& pblock, int nHeight) { + auto dmcTxIter = [&](std::function call) { + for (size_t i = 0; i < pblock.vtx.size(); i++) { + auto tx = pblock.vtx[i]; + std::vector metadata; + const auto txType = GuessCustomTxType(*tx.get(), metadata); + if (txType == CustomTxType::MetachainBridge) { + auto txMessage = customTypeToMessage(txType); + auto res = CustomMetadataParse(static_cast(nHeight), Params().GetConsensus(), metadata, txMessage); + if (!res) { + return res; + } + auto mcMsg = std::get(txMessage); + if (mcMsg.direction == CMetachainMessage::Direction::ToMetachain) { + call(mcMsg.from.GetHex(), mcMsg.to.GetHex(), int64_t(mcMsg.amount)); + } + } + } + return Res::Ok(); + }; + + if (is_ffi) { + std::vector txs; + auto res = dmcTxIter([&](std::string from, std::string to, int64_t amount) { + txs.push_back(DmcTx{from, to, amount}); + }); + if (!res) { + return res; + } + + try { + auto block = mint_block(txs); + std::copy(block.payload.begin(), block.payload.end(), std::back_inserter(pblock.dmc_payload)); + } catch (const std::exception& e) { + return Res::Err(e.what()); + } + } else { + auto inp = MakeMetaBlockInput(); + auto res = dmcTxIter([&](std::string from, std::string to, int64_t amount) { + inp.txs.push_back(MetaTransaction{from, to, amount}); + }); + if (!res) { + return res; + } + + try { + auto client = NewClient(rpc_url); + auto block = CallMetaMintBlock(client, inp); + std::copy(block.payload.begin(), block.payload.end(), std::back_inserter(pblock.dmc_payload)); + } catch (const std::exception& e) { + return Res::Err(e.what()); + } + } + + return Res::Ok(); +} + +Res ConnectDmcBlock(const CBlock& block) { + return Res::Ok(); +} + +Res AddNativeTx(CBlock& pblock, std::unique_ptr &pblocktemplate, int32_t txVersion, int nHeight) { + std::vector txs; + + // NOTE: List of all relevant transactions i.e., only those tx's involving funds + // that have been burned at DMC and supposed to be moved over to native + std::vector incoming; // TODO: Call metachain for getting associated tx + + for (size_t i = 0; i < incoming.size(); i++) { + auto tx = incoming[i]; + CMetachainMessage msg{}; + msg.direction = CMetachainMessage::Direction::FromMetachain; + try { + msg.from = DecodeScript(std::string(tx.from)); // metachain address + msg.to = DecodeMetachainAddress(std::string(tx.to)); // native chain address + } catch (const std::exception& e) { + return Res::Err(e.what()); + } + msg.amount = CAmount(tx.amount); + + CDataStream metadata(DfTxMarker, SER_NETWORK, PROTOCOL_VERSION); + metadata << static_cast(CustomTxType::MetachainBridge) + << msg; + + CMutableTransaction mTx(txVersion); + mTx.vin.resize(1); + mTx.vin[0].prevout.SetNull(); + mTx.vin[0].scriptSig = CScript() << nHeight << OP_0; + mTx.vout.resize(1); + mTx.vout[0].scriptPubKey = CScript() << OP_RETURN << ToByteVector(metadata); + mTx.vout[0].nValue = 0; + pblock.vtx.push_back(MakeTransactionRef(std::move(mTx))); + pblocktemplate->vTxFees.push_back(0); + pblocktemplate->vTxSigOpsCost.push_back(WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock.vtx.back())); + } + + return Res::Ok(); +} diff --git a/src/dmc_handler.h b/src/dmc_handler.h new file mode 100644 index 0000000000..1077019e6d --- /dev/null +++ b/src/dmc_handler.h @@ -0,0 +1,41 @@ +#ifndef DEFI_DMC_HANDLER_H +#define DEFI_DMC_HANDLER_H + +#include +#include + +/** + * Initializes metachain handler + * + * @throws Exception on failure to instantiate RPC client + * @returns true if RPC handler has been setup and false otherwise + * + * NOTE: This depends on ArgsManager, so it must be called only after parsing arguments + */ +bool SetupMetachainHandler(); + +/** + * Instructs the metachain node to mint a block using the newly minted miner block + * + * @param[in] pblock Recently mined block + * @param[in] nHeight Block height + * @returns Ok on successfully adding serialized metachain block data to the minted block +*/ +Res MintDmcBlock(CBlock& pblock, int nHeight); + +/** + * Instructs the metachain node to connect the given block + * + * @param[in] block Recently mined block + * @returns Ok on successfully connecting the block + */ +Res ConnectDmcBlock(const CBlock& block); + +/** + * Instructs the metachain node to get the transactions for moving funds back + * to native chain (if any) + * + */ +Res AddNativeTx(CBlock& pblock, std::unique_ptr& pblocktemplate, int32_t txVersion, int nHeight); + +#endif // DEFI_DMC_HANDLER_H diff --git a/src/init.cpp b/src/init.cpp index d8d8a856c4..f10a8ad4c4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -39,9 +42,9 @@ #include #include #include -#include #include #include +#include #include #include #include