Skip to content

Commit

Permalink
build bitcoin core from sources, add support for savefeeestimate sync
Browse files Browse the repository at this point in the history
  • Loading branch information
greenaddress authored and nitramiz committed Jan 18, 2022
1 parent 87b66ce commit caf7548
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 24 deletions.
16 changes: 8 additions & 8 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ plan_bitcoin_mainnet:
-var "initial_delay_sec=1200"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/_sync/mempool"
-var "fullurl=https://blockstream.info/_sync"
-input=false)

deploy_bitcoin_mainnet:
Expand Down Expand Up @@ -240,7 +240,7 @@ deploy_bitcoin_mainnet:
-var "initial_delay_sec=1200"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/_sync/mempool"
-var "fullurl=https://blockstream.info/_sync"
-input=false -auto-approve)

plan_bitcoin_testnet:
Expand All @@ -263,7 +263,7 @@ plan_bitcoin_testnet:
-var "initial_delay_sec=600"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/testnet/_sync/mempool"
-var "fullurl=https://blockstream.info/testnet/_sync"
-input=false)

deploy_bitcoin_testnet:
Expand Down Expand Up @@ -294,7 +294,7 @@ deploy_bitcoin_testnet:
-var "initial_delay_sec=600"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/testnet/_sync/mempool"
-var "fullurl=https://blockstream.info/testnet/_sync"
-input=false -auto-approve)

plan_liquid_mainnet:
Expand All @@ -317,7 +317,7 @@ plan_liquid_mainnet:
-var "initial_delay_sec=900"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/liquid/_sync/mempool"
-var "fullurl=https://blockstream.info/liquid/_sync"
-input=false)

deploy_liquid_mainnet:
Expand Down Expand Up @@ -348,7 +348,7 @@ deploy_liquid_mainnet:
-var "initial_delay_sec=900"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/liquid/_sync/mempool"
-var "fullurl=https://blockstream.info/liquid/_sync"
-input=false -auto-approve)

plan_liquid_testnet:
Expand All @@ -371,7 +371,7 @@ plan_liquid_testnet:
-var "initial_delay_sec=900"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/liquidtestnet/_sync/mempool"
-var "fullurl=https://blockstream.info/liquidtestnet/_sync"
-input=false)

deploy_liquid_testnet:
Expand Down Expand Up @@ -402,7 +402,7 @@ deploy_liquid_testnet:
-var "initial_delay_sec=900"
-var "image_source_project=$IMAGE_SOURCE_PROJECT"
-var "mempooldat=$MEMPOOLDAT"
-var "fullurl=https://blockstream.info/liquidtestnet/_sync/mempool"
-var "fullurl=https://blockstream.info/liquidtestnet/_sync"
-input=false -auto-approve)

deploy_staging_bitcoin_mainnet:
Expand Down
45 changes: 33 additions & 12 deletions Dockerfile.deps
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,45 @@ RUN sh -c '[ -n "$NO_LIQUID" ] && mkdir -p /wally/wally_dist || ( \
FROM debian:bullseye@sha256:4d6ab716de467aad58e91b1b720f0badd7478847ec7a18f66027d0f8a329a43c
SHELL ["/bin/bash", "-c"]

ENV CORE_BUILD_DEPS="autoconf autotools-dev automake libtool pkg-config bsdmainutils build-essential"
ENV ESPLORA_BUILD_DEPS="clang cmake curl git"
RUN mkdir -p /srv/explorer \
&& apt-get -yqq update \
&& apt-get -yqq upgrade \
&& apt-get -yqq install clang cmake curl git tor
&& apt-get -yqq install ${ESPLORA_BUILD_DEPS} tor ${CORE_BUILD_DEPS}


RUN git clone --quiet --depth 1 --single-branch --branch v0.39.0 https://github.com/nvm-sh/nvm.git /root/.nvm \
&& rm -rf /root/.nvm/.git \
&& source /root/.nvm/nvm.sh \
&& nvm install v17.1.0

ENV SHA256SUM_BITCOINCORE=59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16
ENV VERSION_BITCOINCORE=22.0
RUN curl -sL -o bitcoin.tar.gz "https://bitcoincore.org/bin/bitcoin-core-${VERSION_BITCOINCORE}/bitcoin-${VERSION_BITCOINCORE}-x86_64-linux-gnu.tar.gz" \
&& echo "${SHA256SUM_BITCOINCORE} bitcoin.tar.gz" | sha256sum --check \
&& tar xzf bitcoin.tar.gz -C /srv/explorer \
&& ln -s "/srv/explorer/bitcoin-${VERSION_BITCOINCORE}" /srv/explorer/bitcoin \
&& rm bitcoin.tar.gz
# Build core from sources until PR https://github.com/bitcoin/bitcoin/pull/23387 is merged
ENV CORE_PATCH=contrib/0001-add-support-to-save-fee-estimates-without-shutting-d.patch
ENV CORE_SRC=/root/bitcoin
COPY ${CORE_PATCH} /${CORE_PATCH}
RUN git clone --quiet --depth 1 --branch v22.0 --single-branch --recursive https://github.com/bitcoin/bitcoin.git ${CORE_SRC} \
&& (cd ${CORE_SRC} \
&& git checkout a0988140b71485ad12c3c3a4a9573f7c21b1eff8 \
&& git apply /${CORE_PATCH} \
&& (cd depends \
&& make HOST=x86_64-pc-linux-gnu NO_QT=1 -j $(grep ^processor /proc/cpuinfo | wc -l)) \
&& ./autogen.sh \
&& CONFIG_SITE=$PWD/depends/x86_64-pc-linux-gnu/share/config.site ./configure --prefix=/srv/explorer/bitcoin --disable-man --disable-zmq --disable-qt --disable-gui-tests --disable-bench \
--enable-experimental-asm --without-utils --enable-util-cli --without-libs --with-daemon --disable-maintainer-mode \
--disable-glibc-back-compat --disable-ccache --disable-dependency-tracking --disable-tests --with-gui=no \
&& make -j $(grep ^processor /proc/cpuinfo | wc -l) \
&& make install -j $(grep ^processor /proc/cpuinfo | wc -l) \
&& strip /srv/explorer/bitcoin/bin/* \
&& rm -fr ${CORE_SRC} /${CORE_PATCH})

#ENV SHA256SUM_BITCOINCORE=59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16
#ENV VERSION_BITCOINCORE=22.0
#RUN curl -sL -o bitcoin.tar.gz "https://bitcoincore.org/bin/bitcoin-core-${VERSION_BITCOINCORE}/bitcoin-${VERSION_BITCOINCORE}-x86_64-linux-gnu.tar.gz" \
# && echo "${SHA256SUM_BITCOINCORE} bitcoin.tar.gz" | sha256sum --check \
# && tar xzf bitcoin.tar.gz -C /srv/explorer \
# && ln -s "/srv/explorer/bitcoin-${VERSION_BITCOINCORE}" /srv/explorer/bitcoin \
# && rm bitcoin.tar.gz

ENV SHA256SUM_ELEMENTS=ebe1f0c6e8510c3059a82936f61a64c2353a193409be245761de05f3152fbe53
ENV VERSION_ELEMENTS=0.21.0.1
Expand All @@ -47,18 +69,17 @@ RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.56.1
RUN source /root/.cargo/env \
&& mkdir -p /srv/explorer/electrs{,_liquid} \
&& git clone --no-checkout https://github.com/blockstream/electrs.git \
&& cd electrs \
&& (cd electrs \
&& git checkout 703c6a20d52b61a234a18812503bd754d448992a \
&& cp contrib/popular-scripts.txt /srv/explorer \
&& cargo install --root /srv/explorer/electrs_bitcoin --locked --path . --features electrum-discovery \
&& cargo install --root /srv/explorer/electrs_liquid --locked --path . --features electrum-discovery,liquid \
&& cd .. \
&& rm -fr /root/.cargo electrs \
&& strip /srv/explorer/electrs_*/bin/electrs
&& strip /srv/explorer/electrs_*/bin/electrs)


# cleanup
RUN apt-get --auto-remove remove -yqq --purge clang cmake manpages curl git \
RUN apt-get --auto-remove remove -yqq --purge ${ESPLORA_BUILD_DEPS} manpages ${CORE_BUILD_DEPS} \
&& apt-get clean \
&& apt-get autoclean \
&& rm -rf /usr/share/doc* /usr/share/man /usr/share/postgresql/*/man /var/lib/apt/lists/* /var/cache/* /tmp/* /root/.cache /*.deb /root/.cargo
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.tor
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RUN wget $TORGZ.asc && wget $TORGZ
RUN gpg --keyserver pool.sks-keyservers.net --recv-keys 0x6AFEE6D49E92B601 \
&& gpg --verify tor-$TOR_VER.tar.gz.asc || { echo "Couldn't verify sig"; exit; }
RUN tar xfz tor-$TOR_VER.tar.gz && cd tor-$TOR_VER \
&& ./configure && make install
&& ./configure && make -j $(grep ^processor /proc/cpuinfo | wc -l) install

FROM alpine@sha256:ab00606a42621fb68f2ed6ad3c88be54397f981a7b70a79db3d1172b11c4367d

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
From 3cf380db8f763f4522ef1bda21b3c5f200dced75 Mon Sep 17 00:00:00 2001
From: Lawrence Nahum <[email protected]>
Date: Fri, 29 Oct 2021 17:39:28 +0200
Subject: [PATCH] add support to save fee estimates without shutting down the
node

---
src/policy/fees.cpp | 18 ++++---
src/policy/fees.h | 3 ++
src/rpc/misc.cpp | 27 ++++++++++
src/test/fuzz/rpc.cpp | 1 +
.../feature_fee_estimates_persist.py | 54 +++++++++++++++++++
test/functional/test_runner.py | 1 +
6 files changed, 98 insertions(+), 6 deletions(-)
create mode 100755 test/functional/feature_fee_estimates_persist.py

diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp
index 2ae5798eb..8a5ac99fb 100644
--- a/src/policy/fees.cpp
+++ b/src/policy/fees.cpp
@@ -883,12 +883,7 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation

void CBlockPolicyEstimator::Flush() {
FlushUnconfirmed();
-
- fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
- CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
- if (est_file.IsNull() || !Write(est_file)) {
- LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", est_filepath.string());
- }
+ Write();
}

bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
@@ -916,6 +911,17 @@ bool CBlockPolicyEstimator::Write(CAutoFile& fileout) const
return true;
}

+bool CBlockPolicyEstimator::Write() const
+{
+ fs::path est_filepath = gArgs.GetDataDirNet() / FEE_ESTIMATES_FILENAME;
+ CAutoFile est_file(fsbridge::fopen(est_filepath, "wb"), SER_DISK, CLIENT_VERSION);
+ if (est_file.IsNull() || !Write(est_file)) {
+ LogPrintf("Failed to write fee estimates to %s. Continue anyway.\n", est_filepath.string());
+ return false;
+ }
+ return true;
+}
+
bool CBlockPolicyEstimator::Read(CAutoFile& filein)
{
try {
diff --git a/src/policy/fees.h b/src/policy/fees.h
index c444d71a3..9d178d0a6 100644
--- a/src/policy/fees.h
+++ b/src/policy/fees.h
@@ -213,6 +213,9 @@ public:
/** Write estimation data to a file */
bool Write(CAutoFile& fileout) const;

+ /** Write estimation data to the default file */
+ bool Write() const;
+
/** Read estimation data from a file */
bool Read(CAutoFile& filein);

diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp
index 5178ce60e..0050b82a6 100644
--- a/src/rpc/misc.cpp
+++ b/src/rpc/misc.cpp
@@ -14,6 +14,7 @@
#include <key_io.h>
#include <node/context.h>
#include <outputtype.h>
+#include <policy/fees.h>
#include <rpc/blockchain.h>
#include <rpc/server.h>
#include <rpc/util.h>
@@ -328,6 +329,31 @@ static RPCHelpMan verifymessage()
};
}

+static RPCHelpMan savefeeestimates()
+{
+ return RPCHelpMan{"savefeeestimates",
+ "\nDumps the fee estimates to disk. It will fail until the previous dump is fully loaded.\n",
+ {},
+ RPCResult{RPCResult::Type::NONE, "", ""},
+ RPCExamples{
+ HelpExampleCli("savefeeestimates", "")
+ + HelpExampleRpc("savefeeestimates", "")
+ },
+ [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
+{
+ static Mutex dump_mutex;
+ LOCK(dump_mutex);
+ CBlockPolicyEstimator& fee_estimator = EnsureAnyFeeEstimator(request.context);
+
+ if (!fee_estimator.Write()) {
+ throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump fee estimates to disk");
+ }
+
+ return NullUniValue;
+},
+ };
+}
+
static RPCHelpMan signmessagewithprivkey()
{
return RPCHelpMan{"signmessagewithprivkey",
@@ -759,6 +785,7 @@ static const CRPCCommand commands[] =
{ "util", &deriveaddresses, },
{ "util", &getdescriptorinfo, },
{ "util", &verifymessage, },
+ { "util", &savefeeestimates, },
{ "util", &signmessagewithprivkey, },
{ "util", &getindexinfo, },

diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp
index 9195cc487..df41004fa 100644
--- a/src/test/fuzz/rpc.cpp
+++ b/src/test/fuzz/rpc.cpp
@@ -76,6 +76,7 @@ const std::vector<std::string> RPC_COMMANDS_NOT_SAFE_FOR_FUZZING{
"importwallet", // avoid reading from disk
"loadwallet", // avoid reading from disk
"prioritisetransaction", // avoid signed integer overflow in CTxMemPool::PrioritiseTransaction(uint256 const&, long const&) (https://github.com/bitcoin/bitcoin/issues/20626)
+ "savefeeestimates", // disabled as a precautionary measure: may take a file path argument in the future
"savemempool", // disabled as a precautionary measure: may take a file path argument in the future
"setban", // avoid DNS lookups
"stop", // avoid shutdown state
diff --git a/test/functional/feature_fee_estimates_persist.py b/test/functional/feature_fee_estimates_persist.py
new file mode 100755
index 000000000..c6d82345b
--- /dev/null
+++ b/test/functional/feature_fee_estimates_persist.py
@@ -0,0 +1,54 @@
+#!/usr/bin/env python3
+# Copyright (c) 2014-2021 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test fee estimates persistence.
+
+By default, bitcoind will dump fee estimates on shutdown and
+then reload it on startup.
+
+Test is as follows:
+
+ - start node0
+ - call the savefeeestimates RPC and verify the RPC succeeds and
+ that the file exists
+ - make the file read only and attempt to call the savefeeestimates RPC
+ with the expecation that it will fail
+ - move the read only file and shut down the node, verify the node writes
+ on shutdown a file that is identical to the one we saved via the RPC
+
+"""
+
+import filecmp
+import os
+
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import assert_raises_rpc_error
+
+
+class FeeEstimatesPersistTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.num_nodes = 1
+
+ def run_test(self):
+ fee_estimatesdat = os.path.join(self.nodes[0].datadir, self.chain, 'fee_estimates.dat')
+ self.log.debug('Verify the fee_estimates.dat file does not exists on start up')
+ assert not os.path.isfile(fee_estimatesdat)
+ self.nodes[0].savefeeestimates()
+ self.log.debug('Verify the fee_estimates.dat file exists after calling savefeeestimates RPC')
+ assert os.path.isfile(fee_estimatesdat)
+ self.log.debug("Prevent bitcoind from writing fee_estimates.dat to disk. Verify that `savefeeestimates` fails")
+ fee_estimatesdatold = fee_estimatesdat + '.old'
+ os.rename(fee_estimatesdat, fee_estimatesdatold)
+ os.mkdir(fee_estimatesdat)
+ assert_raises_rpc_error(-1, "Unable to dump fee estimates to disk", self.nodes[0].savefeeestimates)
+ os.rmdir(fee_estimatesdat)
+ self.stop_nodes()
+ self.log.debug("Verify that fee_estimates are written on shutdown")
+ assert os.path.isfile(fee_estimatesdat)
+ self.log.debug("Verify that the fee estimates from a shutdown are identical from the ones from savefeeestimates")
+ assert filecmp.cmp(fee_estimatesdat, fee_estimatesdatold)
+
+
+if __name__ == "__main__":
+ FeeEstimatesPersistTest().main()
diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py
index 725706947..a2f50b537 100755
--- a/test/functional/test_runner.py
+++ b/test/functional/test_runner.py
@@ -134,6 +134,7 @@ BASE_SCRIPTS = [
# vv Tests less than 30s vv
'wallet_keypool_topup.py --legacy-wallet',
'wallet_keypool_topup.py --descriptors',
+ 'feature_fee_estimates_persist.py',
'feature_fee_estimation.py',
'interface_zmq.py',
'rpc_invalid_address_message.py',
--
2.20.1

19 changes: 19 additions & 0 deletions contrib/nginx-sync.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,29 @@ location = /{NGINX_PATH}_sync/mempool {
}
}

# Dump the current mempool and return it
location = /{NGINX_PATH}_sync/fee_estimates {
auth_basic "private";
auth_basic_user_file /srv/explorer/htpasswd;

content_by_lua_block {
os.execute("/usr/bin/cli savefeeestimates");
ngx.exec("/_sync/fee_estimates.dat");
}
}

# Return mempool.dat without dumping it first, used as an internal redirect
# from the location block above
location = /{NGINX_PATH}_sync/mempool.dat {
auth_basic "private";
auth_basic_user_file /srv/explorer/htpasswd;
alias {DAEMON_DIR}/mempool.dat;
}

# Return fee_estimates.dat without dumping it first, used as an internal redirect
# from the location block above
location = /{NGINX_PATH}_sync/fee_estimates.dat {
auth_basic "private";
auth_basic_user_file /srv/explorer/htpasswd;
alias {DAEMON_DIR}/fee_estimates.dat;
}
Loading

0 comments on commit caf7548

Please sign in to comment.