mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-20 13:37:28 +02:00
Merge #502: [0.17 MERGE] Merge up to Core 3832c25f17
634e3953fMERGE FIX: Prevent mainnet unit tests from thinking they have signed blocks after custom tests (Gregory Sanders)c42c82329MERGE FIX: Pegin witness test cleanup (Gregory Sanders)6c1c65249MERGE FIX: move pegin witness test to beginning to maybe avoid dirtying other tests (Gregory Sanders)a36ee6c0eMERGE FIX: Augment IsValidPeginWitness with err string return (Gregory Sanders)9d9ee3d51MERGE FIX: Adapt bitcoin_functional sync to regtest2 (Gregory Sanders)7c97d6a81MERGE FIX: sync up bitcoin_functional (Gregory Sanders)949405202MERGE FIX: enable parent chain in fedpeg-based unit tests (Gregory Sanders)c73e56428MERGE FIX: instantiate consensus.has_parent_chain for all chains (Gregory Sanders)4f4fe8f6cMERGE FIX: ConnectTip: ub fix for bench (Gregory Sanders)80857b329MERGE FIX: TEST: fixup bitcoin functional (Gregory Sanders)e0a8aba13MERGE FIX: Properly parse sendtomainchain args from -cli (Gregory Sanders)420267122MERGE FIX: spelling linter fixes (Gregory Sanders)01799727cMERGE FIX: fixup travis bitcoin_functional run (Gregory Sanders)90f7d18c8MERGE-FIX: functional tests (Gregory Sanders)51584e73aMERGE-FIX: various compilation fixes (Gregory Sanders)d641c29a5travis: Run feature_dbcrash functional tests in cron job (Chun Kuan Lee)c0d947d72tests: Reorder tests and move most of extended tests up to normal tests (Chun Kuan Lee)cccc362d6build: Remove libssl from LDADD unless gui (MarcoFalke)8e1c13e6ddoc: Document -checklevel levels (Wladimir J. van der Laan)c1dde3a94No longer shutdown after encrypting the wallet (Andrew Chow)d7637c5a3After encrypting the wallet, reload the database environment (Andrew Chow)5d296ac81Add function to close all Db's and reload the databae environment (Andrew Chow)a769461d5Move BerkeleyEnvironment deletion from internal method to callsite (Andrew Chow)9dcb6763f[qa] Use correct python index slices in example test (Suhas Daftuar)fa8433e37qa: Remove unneded import_deterministic_coinbase_privkeys overwrite, add comments (MarcoFalke)e413c2dddqa: Fix codespell error and have lint-spelling error instead of warn (MarcoFalke)14b29a77aFix reference to lint-locale-dependence.sh (Hennadii Stepanov)e22136893utils: Convert fs error messages from multibyte to utf-8 (Chun Kuan Lee)e4ef4b459[build] remove #ifdef ENABLE_WALLET from interfaces/node (John Newbery)fa6ab8adarpc: Return more specific reject reason for submitblock (MarcoFalke)b16ab9af0Report progress in ReplayBlocks while rolling forward (João Barbosa)b6a253337Remove redundant BIP174 test from rpc_psbt.json (araspitzu)fac953983qa: Run all tests even if wallet is not compiled (MarcoFalke)faa669cbcqa: Premine to deterministic address with -disablewallet (MarcoFalke)d38bf9105Call unicode API on Windows (Chun Kuan Lee)d0b1cee1fdoc: `-help-debug` implies `-help` (Wladimir J. van der Laan)9a565a828Pass export privkey DER compression flag correctly (liuyujun)fae3fbd61logging: Replace LogPrint macros with regular functions (MarcoFalke)e0664f7f5build: Move interfaces/* to libbitcoin_server (Wladimir J. van der Laan)23db9546cutils: run commands using utf-8 string on Windows (Chun Kuan Lee)7d038dcb4[build] remove ENABLE_WALLET ifdef from httprpc.cpp (John Newbery)3076556cd[build] Move dummy wallet into its own .cpp file. (John Newbery)bb6ca65f9gui: get special folder in unicode (Chun Kuan Lee)1c5d22585Drop boost::scoped_array (Chun Kuan Lee)e7a72455fScripts and tools: increased timeout downloading (Emanuele Cisbani)a679109beSpeed up knapsack_solver_test by not recreating wallet 100 times. (lucash.dev@gmail.com)893628be0Drop minor GetSerializeSize template (Ben Woosley)da74db094Drop unused GetType() from CSizeComputer (Ben Woosley)b9babc82dutils: Use _wfopen and _wreopen on Windows (Chun Kuan Lee)fa7e9694eqt: Also log and print messages or questions like bitcoind (MarcoFalke)dd031e383noui: Move handlers to header file (MarcoFalke)fa263bcfeqa: Fix silent merge conflict in wallet_importmulti (MarcoFalke)98ea64cf2Let wallet importmulti RPC accept labels for standard scriptPubKeys (Russell Yanofsky)faa1a7494tx pool: Use class methods to hide raw map iterator impl details (MarcoFalke)d9d79576fPreserve a format of RPC command definitions (Kostiantyn Stepaniuk)9256f7d13build: avoid getifaddrs when unavailable (Cory Fields)fa462b365wallet: Set encrypted_batch to nullptr after delete. Avoid double free in the case of NDEBUG. (practicalswift)faea5bfc5doc: release notes for -enablebip61 default change (MarcoFalke)fa14b54a8p2p: Disable BIP 61 by default (MarcoFalke)7177e093fdepends: Remove unused Qt 4 dependencies (Chun Kuan Lee)dc287c98fSquashed 'src/univalue/' changes from 51d3ab34ba..7890db99d6 (MarcoFalke)946107a68Only log "Using PATH_TO_bitcoin.conf" message on startup if conf file exists. (Alexander Leishman)bc8aa2ba7don't translate command line options (Michael Polzer)fac3e22b1qa: Read reject reasons from debug log, not p2p messages (MarcoFalke)b2f49bd73Integration of property based testing into Bitcoin Core (Chris Stewart)65a449f8eExplain when reindex-chainstate can be used instead of reindex (Sjors Provoost)e351a16a2Remove reference to deprecated RPC call in build instructions (Michael Goldstein)a6f16f1b1Docs: Add disable-wallet section to OSX build instructions (Michael Goldstein)f7e9e7046[rpc] Remove deprecated sigrawtransaction rpc method. (John Newbery)90c834089[RPC] Remove warning about wallet addresses in createmultisig() (John Newbery)df905e390[rpc] Remove deprecated validateaddress usage. (John Newbery)fab526751doxygen: Remove misleading checkpoints comment in CMainParams (MarcoFalke)2b5d6f8dfReplace duplcate reference with reference to reference doc (Pieter Wuille)89709db7aAdjust TODO link (Pieter Wuille)9254ffcf2Add descriptor reference documentation (Pieter Wuille)ed2332aeftest: Add test for config file parsing errors (MarcoFalke)a66c0f78autil: Report parse errors in configuration file (Wladimir J. van der Laan)f8a81f73alint: Add spell check linter (codespell) (practicalswift)ada356208Fix typos reported by codespell (practicalswift)e9a78e9b3doc: Change documentation for =0 for non-boolean options (Wladimir J. van der Laan)341f7c7b0macOS fix: Check for correct version of flake8 to avoid spurious warnings. The brew installed flake8 version is Python 2 based and does not work. (practicalswift)908a559f3macOS fix: Add excludes for checks added in the newer shellcheck version installed by brew (practicalswift)ec4d57bbbmacOS fix: Work around empty (sub)expression error when using BSD grep (practicalswift)b57d7d92fmacOS fix: Avoid mapfile due to ancient version of bash shipped with macOS (practicalswift)e4a79b4b3appveyor: Use clcache to speed up build (Chun Kuan Lee)f34c8c466Make objects in range declarations immutable by default. Avoid unnecessary copying of objects in range declarations. (practicalswift)ee3a494f3gui: Favor macOS show / hide action in dock menu (João Barbosa)e8c4a1e36Add new regtest ports in doc following #10825 ports reattributions (Antoine Riard)8ecaee13fIncrease signal to noise in appveyor build output by reducing the MSVC warning count from 12 to 4 (12 is assuming the changes in #14086 are also implemented). (practicalswift)5d62dcf9clint: Make sure we read the command line inputs using utf-8 decoding in python (Chun Kuan Lee)c7f7fa467Trivial: update clang thread-safety docs url (Ben Woosley)68bfc0bcedoc: correct GetDifficulty doc after #13288 (fanquake)83d53058aSwitch nPrevNodeCount to vNodesSize. (Patrick Strateman)fb97437efadded note that control port must be enabled and how to do that in torrc config file (Jordan Baczuk)8dfc2f30dTest rpc_help.py failed: Check whether ZMQ is enabled or not. (Kvaciral)190bf62bescripted-diff: Small locking rename (Russell Yanofsky)9c4dc597dUse LOCK macros for non-recursive locks (Russell Yanofsky)1382913e6Make LOCK, LOCK2, TRY_LOCK work with CWaitableCriticalSection (Russell Yanofsky)ba1f095aaMOVEONLY Move AnnotatedMixin declaration (Russell Yanofsky)41b88e933Add unit test for DEBUG_LOCKORDER code (Russell Yanofsky)62b6f0f21Add EXCLUSIVE_LOCKS_REQUIRED to CWallet::ListCoins (Russell Yanofsky)545e85eccAdd AssertLockHeld assertions in CWallet::ListCoins (Russell Yanofsky)ca1a09312Add regression test: Don't assert(...) with side effects (practicalswift)4c3c9c386Don't assert(...) with side effects (practicalswift)b602c9b3atests: Add missing locking annotations and locks (practicalswift)f05599557blockfilter: Omit empty scripts from filter contents. (Jim Posen)75ea00f39Remove unused fsbridge::freopen (practicalswift)cceedbc4bDon't close old debug log file handle prematurely when trying to re-open (on SIGHUP) (practicalswift)fa782a308qa: Use named args in some tests (MarcoFalke)b4d330967scripted-diff: Use named arguments in feature_block (MarcoFalke)749ba35e7scripted-diff: Pass node into p2p_segwit acceptance tests (MarcoFalke)8550f1fb2Add README.md to linux release tarballs (Hennadii Stepanov)c516c3a77[contrib] Support ARM and RISC-V symbol check (Chun Kuan Lee)c9c32e6b8[wallet] Kill accounts (John Newbery)1e29379d6Fix potential deadlock (practicalswift)d58dc9f94Add lock annotations (cs_args) (practicalswift)db5e9d3c8Add missing locks (cs_args) (practicalswift)0e534d4dcFix incorrect Doxygen comments (practicalswift)fa309dc30validation: Log FormatStateMessage on ConnectBlock error in ConnectTip (MarcoFalke)fa587773escripted-diff: Remove unused first argument to addUnchecked (MarcoFalke)fe5c49766tx pool: Use the entry's hash instead of the one passed to addUnchecked (MarcoFalke)ddd395f96Mark CTxMemPoolEntry members that should not be modified const (MarcoFalke)6af6d9b23test: Add tests for RPC help (João Barbosa)1d9aa008dExplicitly initialize prevector _union (Ben Woosley)b193d5a44Removes the Boost case_conv.hpp dependency. (251)7a208d9faImplements custom tolower and toupper functions. (251)e2ba043b8Implements ParseNetwork unit test. (251)1661a472badd unicode compatible file_lock for Windows (Chun Kuan Lee)1cc58978btests: Fix accidental trunction from int to bool (practicalswift)61fe653bdfix walletcreatefundedpsbt deriv paths, add test (Gregory Sanders)fae040010qa: Add some actual witness in rpc_rawtransaction (MarcoFalke)917353c8bMake SignPSBTInput operate on a private SignatureData object (Pieter Wuille)cad5dd236Pass HD path data through SignatureData (Pieter Wuille)03a99586aImplement key origin lookup in CWallet (Pieter Wuille)3b01efa0d[MOVEONLY] Move ParseHDKeypath to utilstrencodings (Pieter Wuille)81e1dd5ceGeneralize PublicOnlySigningProvider into HidingSigningProvider (Pieter Wuille)84f1f1bfdMake SigningProvider expose key origin information (Pieter Wuille)611ab307fIntroduce KeyOriginInfo for fingerprint + path (Pieter Wuille)16e288acdtest padding non micro timestamps (John Newbery)995dd89d8[Tests] Make combine_logs.py handle multi-line logs (John Newbery)4c530e010travis: add CXXFLAGS=-Wnopsabi at ARM job (Chun Kuan Lee)dd777f3e1Remove unused variable (practicalswift)cdf408945Remove redundant assignments (dead stores) (practicalswift)1ac3c983bMark single-argument constructors "explicit" (practicalswift)bb08423d5[doc] Add release notes for 'account' API removal (John Newbery)1f4b865e5[wallet] Re-sort wallet RPC commands (John Newbery)f0dc850bf[wallet] Remove wallet account RPCs (John Newbery)c410f4157[tests] Remove wallet accounts test (John Newbery)c55c5f2b1fix missing differentiation between UNIT and FUNCTIONAL tests in travis build (Julian Fleischer)414326952use export LC_ALL=C.UTF-8 (Julian Fleischer)728c82d02make script exit if a command fails (Julian Fleischer)506890b24move remaining travis build steps into individual files (Julian Fleischer)272306ea5number .travis/ script according to build lifecycle and add README to explain (Julian Fleischer)519e2739cmove lint stage up to resemble travis build ui (Julian Fleischer)86d34f0e6abort script in END_FOLD on non-zero exit code (Julian Fleischer)4f2f88c7bmove script sections info individual files and comply with shellcheck (Julian Fleischer)a9910d82ccontrib: Adjust output to current test format (Akio Nakamura)5778bf95dReport minfeefilter value in getpeerinfo rpc (Anthony Towns)384273260test: Add testing of value_ret for SelectCoinsBnB (Ben Woosley)497e90c02Remove default argument to prevector constructor to remove ambiguity (Ben Woosley)f1640d093Make IS_TRIVIALLY_CONSTRUCTIBLE consistent on GCC < 5 (Ben Woosley)fad8afa38travis: Run unit tests --with-sanitizers=undefined (MarcoFalke)0d00fd590depends: allow CC/CXX to be overridden during configure (Cory Fields)7d0a8ad31Docs: Fix help message typo optiona -> optional (Ben Woosley)faf4a9b67qa: Stop txindex thread before calling destructor (MarcoFalke)0b16f679dauto generate MSVC project files (Chun Kuan Lee)254c85b68bench: Benchmark GCS filter creation and matching. (Jim Posen)f33b717a8blockfilter: Optimization on compilers with int128 support. (Jim Posen)97b64d67dblockfilter: Unit test against BIP 158 test vectors. (Jim Posen)a4afb9cadblockfilter: Additional helper methods to compute hash and header. (Jim Posen)cd09c7925blockfilter: Serialization methods on BlockFilter. (Jim Posen)c1855f605blockfilter: Construction of basic block filters. (Jim Posen)53e7874e0blockfilter: Simple test for GCSFilter construction and Match. (Jim Posen)558c536e3blockfilter: Implement GCSFilter Match methods. (Jim Posen)cf70b5500blockfilter: Implement GCSFilter constructors. (Jim Posen)c454f0ac6blockfilter: Declare GCSFilter class for BIP 158 impl. (Jim Posen)9b622dc72streams: Unit tests for BitStreamReader and BitStreamWriter. (Jim Posen)fe943f99bstreams: Implement BitStreamReader/Writer classes. (Jim Posen)87f2d9ee4streams: Unit test for VectorReader class. (Jim Posen)947133decstreams: Create VectorReader stream interface for vectors. (Jim Posen)737670c03Use assert when running from multithreaded code as BOOST_CHECK_* are not thread safe (Jesse Cohen)9e2de6b9dMove cs_main locking annotations from .cpp to .h (practicalswift)9e0a51411Add compile time checking for all cs_main runtime locking assertions (practicalswift)870bd4c73Update functional RBF test to check replaceable flag (dexX7)820d31f95Add "bip125-replaceable" flag to mempool RPCs (dexX7)03a2d6801Tests: add usage note to check-rpc-mappings.py (Mason Simon)ddddce0e4util: Replace boost::signals2 with std::function (MarcoFalke)fa6c3dea4p2p: Clarify control flow in ProcessMessage() (MarcoFalke)984d72ec6Return the script type from Solver (Ben Woosley)23f434378Add CMerkleTx::IsImmatureCoinBase method (Ben Woosley)fa3e9f762qa: Add TestNode::assert_debug_log (MarcoFalke)00f58f8c4rpc: Avoid locking cs_main in some wallet RPC (João Barbosa)fa74d3d72qa: Remove unused deserialization code in msg_version (MarcoFalke)fa5099cebp2p: Remove dead code for nVersion=10300 (MarcoFalke)856334171Bugfix: NSIS: Exclude Makefile* from docs (Luke Dashjr)46f834537contrib: Support github pull request gitian-build (Chun Kuan Lee)317f2cb3ftest: Check RPC settxfee errors (João Barbosa)48618daf2Add checks for settxfee reasonableness (Anthony Towns)321159e53don't report minversion wallet entry as unknown (Gregory Sanders)19efc01aeAdd PSBT documentation (Pieter Wuille)18c49eb88http: Add const modifier to HTTPRequest methods (João Barbosa)3567b247ftest: Add lint to prevent SIGNAL/SLOT connect style (João Barbosa)f78558f1eqt: Use new Qt5 connect syntax (João Barbosa) Pull request description: Tree-SHA512: 6da8dacc63f7ca6f28ed6aa0143cc65383d9ac17fcad26c17b683397701ba170b3987fa0f246ef8408766975d7b80b62c5ff8a20cfcb78ce54d65b8a620e9e91
This commit is contained in:
commit
e51ed82876
445 changed files with 6224 additions and 5131 deletions
147
.travis.yml
147
.travis.yml
|
|
@ -5,19 +5,19 @@ language: minimal
|
|||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- depends/built
|
||||
- depends/sdk-sources
|
||||
- $HOME/.ccache
|
||||
- depends/built
|
||||
- depends/sdk-sources
|
||||
- $HOME/.ccache
|
||||
stages:
|
||||
- lint
|
||||
- test
|
||||
env:
|
||||
global:
|
||||
- MAKEJOBS=-j3
|
||||
- RUN_TESTS=false
|
||||
- RUN_UNIT_TESTS=true
|
||||
- RUN_FUNCTIONAL_TESTS=true
|
||||
- RUN_BENCH=false # Set to true for any one job that has debug enabled, to quickly check bench is not crashing or hitting assertions
|
||||
- DOCKER_NAME_TAG=ubuntu:18.04
|
||||
- LC_ALL=C.UTF-8
|
||||
- BOOST_TEST_RANDOM=1$TRAVIS_BUILD_ID
|
||||
- CCACHE_SIZE=100M
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
|
|
@ -28,55 +28,43 @@ env:
|
|||
- WINEDEBUG=fixme-all
|
||||
- DOCKER_PACKAGES="build-essential libtool autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache"
|
||||
before_install:
|
||||
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
|
||||
- BEGIN_FOLD () { echo ""; CURRENT_FOLD_NAME=$1; echo "travis_fold:start:${CURRENT_FOLD_NAME}"; }
|
||||
- END_FOLD () { RET=$?; echo "travis_fold:end:${CURRENT_FOLD_NAME}"; return $RET; }
|
||||
- set -o errexit; source .travis/test_03_before_install.sh
|
||||
install:
|
||||
- travis_retry docker pull $DOCKER_NAME_TAG
|
||||
- env | grep -E '^(CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env
|
||||
- if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN"; fi
|
||||
- DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env $DOCKER_NAME_TAG)
|
||||
- DOCKER_EXEC () { docker exec $DOCKER_ID bash -c "cd $PWD && $*"; }
|
||||
- if [ -n "$DPKG_ADD_ARCH" ]; then DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi
|
||||
- travis_retry DOCKER_EXEC apt-get update
|
||||
- travis_retry DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES
|
||||
- set -o errexit; source .travis/test_04_install.sh
|
||||
before_script:
|
||||
- DOCKER_EXEC echo \> \$HOME/.bitcoin # Make sure default datadir does not exist and is never read by creating a dummy file
|
||||
- mkdir -p depends/SDKs depends/sdk-sources
|
||||
- if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [[ $HOST = *-mingw32 ]]; then DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\); fi
|
||||
- if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC CONFIG_SHELL= make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS; fi
|
||||
- set -o errexit; source .travis/test_05_before_script.sh
|
||||
script:
|
||||
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
|
||||
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
|
||||
- BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib"
|
||||
- if [ -z "$NO_DEPENDS" ]; then DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi
|
||||
- BEGIN_FOLD autogen; test -n "$CONFIG_SHELL" && DOCKER_EXEC "$CONFIG_SHELL" -c "./autogen.sh" || DOCKER_EXEC ./autogen.sh; END_FOLD
|
||||
- mkdir build && cd build
|
||||
- BEGIN_FOLD configure; DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false); END_FOLD
|
||||
- BEGIN_FOLD distdir; DOCKER_EXEC make distdir VERSION=$HOST; END_FOLD
|
||||
- cd bitcoin-$HOST
|
||||
- BEGIN_FOLD configure; DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false); END_FOLD
|
||||
- BEGIN_FOLD build; DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false ); END_FOLD
|
||||
- if [ "$RUN_TESTS" = "true" ]; then BEGIN_FOLD unit-tests; DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib make $MAKEJOBS check VERBOSE=1; END_FOLD; fi
|
||||
- if [ "$RUN_BENCH" = "true" ]; then BEGIN_FOLD bench; DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib $OUTDIR/bin/bench_bitcoin -scaling=0.001 ; END_FOLD; fi
|
||||
- if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then extended="--extended --exclude feature_pruning,feature_dbcrash"; fi
|
||||
- if [ "$RUN_TESTS" = "true" ]; then BEGIN_FOLD functional-tests; DOCKER_EXEC test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}; END_FOLD; fi
|
||||
- if [ "$RUN_BITCOIN_TESTS" = "true" ]; then BEGIN_FOLD bitcoin-functional-tests; DOCKER_EXEC test/bitcoin_functional/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}; END_FOLD; fi
|
||||
- set -o errexit; source .travis/test_06_script.sh
|
||||
after_script:
|
||||
- echo $TRAVIS_COMMIT_RANGE
|
||||
- echo $TRAVIS_COMMIT_LOG
|
||||
- echo $TRAVIS_COMMIT_RANGE
|
||||
- echo $TRAVIS_COMMIT_LOG
|
||||
jobs:
|
||||
include:
|
||||
# lint stage
|
||||
- stage: lint
|
||||
env:
|
||||
sudo: false
|
||||
cache: false
|
||||
language: python
|
||||
python: '3.6'
|
||||
install:
|
||||
- set -o errexit; source .travis/lint_04_install.sh
|
||||
before_script:
|
||||
- set -o errexit; source .travis/lint_05_before_script.sh
|
||||
script:
|
||||
- set -o errexit; source .travis/lint_06_script.sh
|
||||
# ARM
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=arm-linux-gnueabihf
|
||||
PACKAGES="g++-arm-linux-gnueabihf"
|
||||
DEP_OPTS="NO_QT=1"
|
||||
RUN_UNIT_TESTS=false
|
||||
RUN_FUNCTIONAL_TESTS=false
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
|
||||
# -Wno-psabi is to disable ABI warnings: "note: parameter passing for argument of type ... changed in GCC 7.1"
|
||||
# This could be removed once the ABI change warning does not show up by default
|
||||
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports CXXFLAGS=-Wno-psabi"
|
||||
# Win32
|
||||
- stage: test
|
||||
env: >-
|
||||
|
|
@ -84,7 +72,6 @@ jobs:
|
|||
DPKG_ADD_ARCH="i386"
|
||||
DEP_OPTS="NO_QT=1"
|
||||
PACKAGES="python3 nsis g++-mingw-w64-i686 wine-binfmt wine32"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-reduce-exports"
|
||||
# Win64
|
||||
|
|
@ -93,7 +80,6 @@ jobs:
|
|||
HOST=x86_64-w64-mingw32
|
||||
DEP_OPTS="NO_QT=1"
|
||||
PACKAGES="python3 nsis g++-mingw-w64-x86-64 wine-binfmt wine64"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-reduce-exports"
|
||||
# 32-bit + dash
|
||||
|
|
@ -102,7 +88,6 @@ jobs:
|
|||
HOST=i686-pc-linux-gnu
|
||||
PACKAGES="g++-multilib python3-zmq"
|
||||
DEP_OPTS="NO_QT=1"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --enable-glibc-back-compat --enable-reduce-exports LDFLAGS=-static-libstdc++"
|
||||
CONFIG_SHELL="/bin/dash"
|
||||
|
|
@ -112,19 +97,45 @@ jobs:
|
|||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools protobuf-compiler libdbus-1-dev libharfbuzz-dev libprotobuf-dev"
|
||||
DEP_OPTS="NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1"
|
||||
RUN_TESTS=true
|
||||
RUN_BENCH=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --with-gui=qt5 --enable-glibc-back-compat --enable-reduce-exports --enable-debug CXXFLAGS=\"-g0 -O2\""
|
||||
# x86_64 Linux (Qt5 & system libs)
|
||||
# x86_64 Linux (no depends, only system libs)
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
|
||||
NO_DEPENDS=1
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER"
|
||||
# x86_64 Linux (sanitizers)
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="clang python3-zmq qtbase5-dev qttools5-dev-tools libssl1.0-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libprotobuf-dev protobuf-compiler libqrencode-dev"
|
||||
NO_DEPENDS=1
|
||||
RUN_BENCH=true
|
||||
RUN_FUNCTIONAL_TESTS=false # Disabled for now, can be combined with the other x86_64 linux NO_DEPENDS job when functional tests pass the sanitizers
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER --with-sanitizers=undefined CC=clang CXX=clang++"
|
||||
# x86_64 Linux, No wallet
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3"
|
||||
DEP_OPTS="NO_WALLET=1"
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
|
||||
# Cross-Mac
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-apple-darwin14
|
||||
PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
|
||||
OSX_SDK=10.11
|
||||
RUN_UNIT_TESTS=false
|
||||
RUN_FUNCTIONAL_TESTS=false
|
||||
GOAL="all deploy"
|
||||
BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror"
|
||||
|
||||
# x86_64 Linux w/ Bitcoin functional tests (Qt5 & system libs)
|
||||
- stage: test
|
||||
env: >-
|
||||
|
|
@ -134,43 +145,3 @@ jobs:
|
|||
RUN_BITCOIN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-zmq --with-incompatible-bdb --enable-glibc-back-compat --enable-reduce-exports --with-gui=qt5 CPPFLAGS=-DDEBUG_LOCKORDER"
|
||||
# x86_64 Linux, No wallet
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-unknown-linux-gnu
|
||||
PACKAGES="python3"
|
||||
DEP_OPTS="NO_WALLET=1"
|
||||
RUN_TESTS=true
|
||||
GOAL="install"
|
||||
BITCOIN_CONFIG="--enable-glibc-back-compat --enable-reduce-exports"
|
||||
# Cross-Mac
|
||||
- stage: test
|
||||
env: >-
|
||||
HOST=x86_64-apple-darwin14
|
||||
PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
|
||||
OSX_SDK=10.11
|
||||
GOAL="all deploy"
|
||||
BITCOIN_CONFIG="--enable-gui --enable-reduce-exports --enable-werror"
|
||||
- stage: lint
|
||||
env:
|
||||
sudo: false
|
||||
cache: false
|
||||
language: python
|
||||
python: '3.6'
|
||||
install:
|
||||
- travis_retry pip install flake8==3.5.0
|
||||
before_script:
|
||||
- git fetch --unshallow
|
||||
script:
|
||||
- if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then test/lint/commit-script-check.sh $TRAVIS_COMMIT_RANGE; fi
|
||||
- test/lint/git-subtree-check.sh src/crypto/ctaes
|
||||
- test/lint/git-subtree-check.sh src/secp256k1
|
||||
- test/lint/git-subtree-check.sh src/univalue
|
||||
- test/lint/git-subtree-check.sh src/leveldb
|
||||
- test/lint/check-doc.py
|
||||
- test/lint/check-rpc-mappings.py .
|
||||
- test/lint/lint-all.sh
|
||||
- if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then
|
||||
while read LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys &&
|
||||
travis_wait 50 contrib/verify-commits/verify-commits.py;
|
||||
fi
|
||||
|
|
|
|||
8
.travis/README.md
Normal file
8
.travis/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
## travis build scripts
|
||||
|
||||
The `.travis` directory contains scripts for each build step in each build stage.
|
||||
Currently the travis build defines two stages `lint` and `test`. Each stage has
|
||||
it's own [lifecycle](https://docs.travis-ci.com/user/customizing-the-build/#the-build-lifecycle).
|
||||
Every script in here is named and numbered according to which stage and lifecycle
|
||||
step it belongs to.
|
||||
|
||||
10
.travis/lint_04_install.sh
Executable file
10
.travis/lint_04_install.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
travis_retry pip install codespell==1.13.0
|
||||
travis_retry pip install flake8==3.5.0
|
||||
9
.travis/lint_05_before_script.sh
Executable file
9
.travis/lint_05_before_script.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
git fetch --unshallow
|
||||
24
.travis/lint_06_script.sh
Executable file
24
.travis/lint_06_script.sh
Executable file
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||
test/lint/commit-script-check.sh $TRAVIS_COMMIT_RANGE
|
||||
fi
|
||||
|
||||
test/lint/git-subtree-check.sh src/crypto/ctaes
|
||||
test/lint/git-subtree-check.sh src/secp256k1
|
||||
test/lint/git-subtree-check.sh src/univalue
|
||||
test/lint/git-subtree-check.sh src/leveldb
|
||||
test/lint/check-doc.py
|
||||
test/lint/check-rpc-mappings.py .
|
||||
test/lint/lint-all.sh
|
||||
|
||||
if [ "$TRAVIS_REPO_SLUG" = "bitcoin/bitcoin" -a "$TRAVIS_EVENT_TYPE" = "cron" ]; then
|
||||
while read -r LINE; do travis_retry gpg --keyserver hkp://subset.pool.sks-keyservers.net --recv-keys $LINE; done < contrib/verify-commits/trusted-keys &&
|
||||
travis_wait 50 contrib/verify-commits/verify-commits.py;
|
||||
fi
|
||||
25
.travis/test_03_before_install.sh
Executable file
25
.travis/test_03_before_install.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
|
||||
export PATH
|
||||
|
||||
BEGIN_FOLD () {
|
||||
echo ""
|
||||
CURRENT_FOLD_NAME=$1
|
||||
echo "travis_fold:start:${CURRENT_FOLD_NAME}"
|
||||
}
|
||||
|
||||
END_FOLD () {
|
||||
RET=$?
|
||||
echo "travis_fold:end:${CURRENT_FOLD_NAME}"
|
||||
if [ $RET != 0 ]; then
|
||||
echo "${CURRENT_FOLD_NAME} failed with status code ${RET}"
|
||||
fi
|
||||
}
|
||||
|
||||
26
.travis/test_04_install.sh
Executable file
26
.travis/test_04_install.sh
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
travis_retry docker pull "$DOCKER_NAME_TAG"
|
||||
env | grep -E '^(CCACHE_|WINEDEBUG|LC_ALL|BOOST_TEST_RANDOM|CONFIG_SHELL)' | tee /tmp/env
|
||||
if [[ $HOST = *-mingw32 ]]; then
|
||||
DOCKER_ADMIN="--cap-add SYS_ADMIN"
|
||||
fi
|
||||
DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env $DOCKER_NAME_TAG)
|
||||
|
||||
DOCKER_EXEC () {
|
||||
docker exec $DOCKER_ID bash -c "cd $PWD && $*"
|
||||
}
|
||||
|
||||
if [ -n "$DPKG_ADD_ARCH" ]; then
|
||||
DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH"
|
||||
fi
|
||||
|
||||
travis_retry DOCKER_EXEC apt-get update
|
||||
travis_retry DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES
|
||||
|
||||
25
.travis/test_05_before_script.sh
Executable file
25
.travis/test_05_before_script.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
DOCKER_EXEC echo \> \$HOME/.bitcoin # Make sure default datadir does not exist and is never read by creating a dummy file
|
||||
|
||||
mkdir -p depends/SDKs depends/sdk-sources
|
||||
|
||||
if [ -n "$OSX_SDK" -a ! -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then
|
||||
curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz
|
||||
fi
|
||||
if [ -n "$OSX_SDK" -a -f depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then
|
||||
tar -C depends/SDKs -xf depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz
|
||||
fi
|
||||
if [[ $HOST = *-mingw32 ]]; then
|
||||
DOCKER_EXEC update-alternatives --set $HOST-g++ \$\(which $HOST-g++-posix\)
|
||||
fi
|
||||
if [ -z "$NO_DEPENDS" ]; then
|
||||
DOCKER_EXEC CONFIG_SHELL= make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS
|
||||
fi
|
||||
|
||||
73
.travis/test_06_script.sh
Executable file
73
.travis/test_06_script.sh
Executable file
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (c) 2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
|
||||
TRAVIS_COMMIT_LOG=$(git log --format=fuller -1)
|
||||
export TRAVIS_COMMIT_LOG
|
||||
|
||||
OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
|
||||
BITCOIN_CONFIG_ALL="--disable-dependency-tracking --prefix=$TRAVIS_BUILD_DIR/depends/$HOST --bindir=$OUTDIR/bin --libdir=$OUTDIR/lib"
|
||||
if [ -z "$NO_DEPENDS" ]; then
|
||||
DOCKER_EXEC ccache --max-size=$CCACHE_SIZE
|
||||
fi
|
||||
|
||||
BEGIN_FOLD autogen
|
||||
if [ -n "$CONFIG_SHELL" ]; then
|
||||
DOCKER_EXEC "$CONFIG_SHELL" -c "./autogen.sh"
|
||||
else
|
||||
DOCKER_EXEC ./autogen.sh
|
||||
fi
|
||||
END_FOLD
|
||||
|
||||
mkdir build
|
||||
cd build || (echo "could not enter build directory"; exit 1)
|
||||
|
||||
BEGIN_FOLD configure
|
||||
DOCKER_EXEC ../configure --cache-file=config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
|
||||
END_FOLD
|
||||
|
||||
BEGIN_FOLD distdir
|
||||
DOCKER_EXEC make distdir VERSION=$HOST
|
||||
END_FOLD
|
||||
|
||||
cd "bitcoin-$HOST" || (echo "could not enter distdir bitcoin-$HOST"; exit 1)
|
||||
|
||||
BEGIN_FOLD configure
|
||||
DOCKER_EXEC ./configure --cache-file=../config.cache $BITCOIN_CONFIG_ALL $BITCOIN_CONFIG || ( cat config.log && false)
|
||||
END_FOLD
|
||||
|
||||
BEGIN_FOLD build
|
||||
DOCKER_EXEC make $MAKEJOBS $GOAL || ( echo "Build failure. Verbose build follows." && DOCKER_EXEC make $GOAL V=1 ; false )
|
||||
END_FOLD
|
||||
|
||||
if [ "$RUN_UNIT_TESTS" = "true" ]; then
|
||||
BEGIN_FOLD unit-tests
|
||||
DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib make $MAKEJOBS check VERBOSE=1
|
||||
END_FOLD
|
||||
fi
|
||||
|
||||
if [ "$RUN_BENCH" = "true" ]; then
|
||||
BEGIN_FOLD bench
|
||||
DOCKER_EXEC LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/depends/$HOST/lib $OUTDIR/bin/bench_bitcoin -scaling=0.001
|
||||
END_FOLD
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "cron" ]; then
|
||||
extended="--extended --exclude feature_pruning"
|
||||
fi
|
||||
|
||||
if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then
|
||||
BEGIN_FOLD functional-tests
|
||||
DOCKER_EXEC test/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}
|
||||
END_FOLD
|
||||
fi
|
||||
|
||||
if [ "$RUN_BITCOIN_TESTS" = "true" ]; then
|
||||
BEGIN_FOLD bitcoin-functional-tests
|
||||
DOCKER_EXEC test/bitcoin_functional/functional/test_runner.py --combinedlogslen=4000 --coverage --quiet --failfast ${extended}
|
||||
END_FOLD
|
||||
fi
|
||||
62
appveyor.yml
62
appveyor.yml
|
|
@ -5,33 +5,41 @@ configuration: Release
|
|||
platform: x64
|
||||
environment:
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
cache: C:\tools\vcpkg\installed\
|
||||
CLCACHE_SERVER: 1
|
||||
PACKAGES: boost-filesystem boost-signals2 boost-interprocess boost-test libevent openssl zeromq berkeleydb secp256k1 leveldb
|
||||
cache:
|
||||
- C:\tools\vcpkg\installed
|
||||
- C:\Users\appveyor\clcache
|
||||
- build_msvc\cache
|
||||
init:
|
||||
- cmd: set PATH=C:\Python36-x64;C:\Python36-x64\Scripts;%PATH%
|
||||
install:
|
||||
- cmd: pip install git+https://github.com/frerich/clcache.git
|
||||
- ps: $packages = $env:PACKAGES -Split ' '
|
||||
- ps: for ($i=0; $i -lt $packages.length; $i++) {
|
||||
$env:ALL_PACKAGES += $packages[$i] + ":" + $env:PLATFORM + "-windows-static "
|
||||
}
|
||||
- cmd: git -C C:\Tools\vcpkg pull # This is a temporary fix, can be removed after appveyor update its image to include Microsoft/vcpkg#4046
|
||||
- cmd: vcpkg install %ALL_PACKAGES%
|
||||
- cmd: vcpkg upgrade --no-dry-run
|
||||
- cmd: del /s /q C:\Tools\vcpkg\installed\%PLATFORM%-windows-static\debug # Remove unused debug library
|
||||
before_build:
|
||||
- ps: >-
|
||||
$packages = @(
|
||||
"boost-filesystem",
|
||||
"boost-signals2",
|
||||
"boost-interprocess",
|
||||
"boost-test",
|
||||
"libevent",
|
||||
"openssl",
|
||||
"zeromq",
|
||||
"berkeleydb",
|
||||
"secp256k1",
|
||||
"leveldb"
|
||||
)
|
||||
|
||||
for ($i=0; $i -lt $packages.length; $i++) {
|
||||
$all_packages += $packages[$i] + ":" + $env:PLATFORM + "-windows-static "
|
||||
}
|
||||
|
||||
git -C C:\Tools\vcpkg pull # This is a temporary fix, can be removed after appveyor update its image to include Microsoft/vcpkg#4046
|
||||
|
||||
Invoke-Expression -Command "vcpkg install $all_packages"
|
||||
build:
|
||||
project: build_msvc\bitcoin.sln
|
||||
parallel: true
|
||||
verbosity: minimal
|
||||
- cmd: if not exist build_msvc\cache\ (del build_msvc\cache & mkdir build_msvc\cache)
|
||||
- cmd: if not exist build_msvc\%PLATFORM%\%CONFIGURATION%\ (mkdir build_msvc\%PLATFORM%\%CONFIGURATION%)
|
||||
- cmd: if exist build_msvc\cache\*.iobj (move build_msvc\cache\* build_msvc\%PLATFORM%\%CONFIGURATION%\)
|
||||
- cmd: clcache -M 2147483648
|
||||
- cmd: python build_msvc\msvc-autogen.py
|
||||
- ps: $files = (Get-ChildItem -Recurse | where {$_.extension -eq ".vcxproj"}).FullName
|
||||
- ps: for ($i = 0; $i -lt $files.length; $i++) {
|
||||
(Get-Content $files[$i]).Replace("</RuntimeLibrary>", "</RuntimeLibrary><DebugInformationFormat>None</DebugInformationFormat>").Replace("NDEBUG;", "") | Set-Content $files[$i]
|
||||
}
|
||||
- ps: Start-Process clcache-server
|
||||
build_script:
|
||||
- cmd: msbuild /p:TrackFileAccess=false /p:CLToolExe=clcache.exe build_msvc\bitcoin.sln /m /v:q /nowarn:C4244;C4267;C4715 /nologo
|
||||
after_build:
|
||||
- cmd: move build_msvc\%PLATFORM%\%CONFIGURATION%\*.iobj build_msvc\cache\
|
||||
- cmd: move build_msvc\%PLATFORM%\%CONFIGURATION%\*.ipdb build_msvc\cache\
|
||||
- cmd: del C:\Users\appveyor\clcache\stats.txt
|
||||
test_script:
|
||||
- cmd: build_msvc\%PLATFORM%\Release\test_bitcoin.exe
|
||||
- cmd: build_msvc\%PLATFORM%\%CONFIGURATION%\test_bitcoin.exe
|
||||
deploy: off
|
||||
|
|
|
|||
1
build_msvc/.gitignore
vendored
1
build_msvc/.gitignore
vendored
|
|
@ -8,3 +8,4 @@ packages/*
|
|||
*/Release
|
||||
*/x64
|
||||
*.vcxproj.user
|
||||
*.vcxproj
|
||||
|
|
|
|||
|
|
@ -47,4 +47,10 @@ The instructions below use vcpkg to install the dependencies.
|
|||
leveldb:x64-windows-static
|
||||
```
|
||||
|
||||
- Use Python to generate *.vcxproj from Makefile
|
||||
|
||||
```
|
||||
PS >python msvc-autogen.py
|
||||
```
|
||||
|
||||
- Build in Visual Studio.
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\rpc\client.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
@ -165,43 +165,7 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\base58.h" />
|
||||
<ClInclude Include="..\..\src\bech32.h" />
|
||||
<ClInclude Include="..\..\src\chainparams.h" />
|
||||
<ClInclude Include="..\..\src\coins.h" />
|
||||
<ClInclude Include="..\..\src\compressor.h" />
|
||||
<ClInclude Include="..\..\src\key.h" />
|
||||
<ClInclude Include="..\..\src\keystore.h" />
|
||||
<ClInclude Include="..\..\src\netaddress.h" />
|
||||
<ClInclude Include="..\..\src\netbase.h" />
|
||||
<ClInclude Include="..\..\src\policy\feerate.h" />
|
||||
<ClInclude Include="..\..\src\protocol.h" />
|
||||
<ClInclude Include="..\..\src\scheduler.h" />
|
||||
<ClInclude Include="..\..\src\script\sign.h" />
|
||||
<ClInclude Include="..\..\src\script\standard.h" />
|
||||
<ClInclude Include="..\..\src\warnings.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\base58.cpp" />
|
||||
<ClCompile Include="..\..\src\bech32.cpp" />
|
||||
<ClCompile Include="..\..\src\chainparams.cpp" />
|
||||
<ClCompile Include="..\..\src\coins.cpp" />
|
||||
<ClCompile Include="..\..\src\compressor.cpp" />
|
||||
<ClCompile Include="..\..\src\core_read.cpp" />
|
||||
<ClCompile Include="..\..\src\core_write.cpp" />
|
||||
<ClCompile Include="..\..\src\key.cpp" />
|
||||
<ClCompile Include="..\..\src\key_io.cpp" />
|
||||
<ClCompile Include="..\..\src\keystore.cpp" />
|
||||
<ClCompile Include="..\..\src\netaddress.cpp" />
|
||||
<ClCompile Include="..\..\src\netbase.cpp" />
|
||||
<ClCompile Include="..\..\src\policy\feerate.cpp" />
|
||||
<ClCompile Include="..\..\src\protocol.cpp" />
|
||||
<ClCompile Include="..\..\src\scheduler.cpp" />
|
||||
<ClCompile Include="..\..\src\script\descriptor.cpp" />
|
||||
<ClCompile Include="..\..\src\script\sign.cpp" />
|
||||
<ClCompile Include="..\..\src\script\ismine.cpp" />
|
||||
<ClCompile Include="..\..\src\script\standard.cpp" />
|
||||
<ClCompile Include="..\..\src\warnings.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
@ -151,25 +151,7 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\crypto\aes.h" />
|
||||
<ClInclude Include="..\..\src\crypto\chacha20.h" />
|
||||
<ClInclude Include="..\..\src\crypto\common.h" />
|
||||
<ClInclude Include="..\..\src\crypto\hmac_sha256.h" />
|
||||
<ClInclude Include="..\..\src\crypto\hmac_sha512.h" />
|
||||
<ClInclude Include="..\..\src\crypto\ripemd160.h" />
|
||||
<ClInclude Include="..\..\src\crypto\sha1.h" />
|
||||
<ClInclude Include="..\..\src\crypto\sha256.h" />
|
||||
<ClInclude Include="..\..\src\crypto\sha512.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\crypto\aes.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\chacha20.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\hmac_sha256.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\hmac_sha512.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\ripemd160.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\sha1.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\sha256.cpp" />
|
||||
<ClCompile Include="..\..\src\crypto\sha512.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<Import Label="configTarget" Project="..\common.vcxproj" />
|
||||
</Project>
|
||||
|
|
@ -154,53 +154,13 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\addrdb.cpp" />
|
||||
<ClCompile Include="..\..\src\addrman.cpp" />
|
||||
<ClCompile Include="..\..\src\blockencodings.cpp" />
|
||||
<ClCompile Include="..\..\src\bloom.cpp" />
|
||||
<ClCompile Include="..\..\src\chain.cpp" />
|
||||
<ClCompile Include="..\..\src\checkpoints.cpp" />
|
||||
<ClCompile Include="..\..\src\consensus\tx_verify.cpp" />
|
||||
<ClCompile Include="..\..\src\dbwrapper.cpp" />
|
||||
<ClCompile Include="..\..\src\httprpc.cpp" />
|
||||
<ClCompile Include="..\..\src\httpserver.cpp" />
|
||||
<ClCompile Include="..\..\src\index\base.cpp" />
|
||||
<ClCompile Include="..\..\src\init.cpp" />
|
||||
<ClCompile Include="..\..\src\merkleblock.cpp" />
|
||||
<ClCompile Include="..\..\src\miner.cpp" />
|
||||
<ClCompile Include="..\..\src\net.cpp" />
|
||||
<ClCompile Include="..\..\src\net_processing.cpp" />
|
||||
<ClCompile Include="..\..\src\noui.cpp" />
|
||||
<ClCompile Include="..\..\src\outputtype.cpp" />
|
||||
<ClCompile Include="..\..\src\policy\fees.cpp" />
|
||||
<ClCompile Include="..\..\src\policy\policy.cpp" />
|
||||
<ClCompile Include="..\..\src\policy\rbf.cpp" />
|
||||
<ClCompile Include="..\..\src\pow.cpp" />
|
||||
<ClCompile Include="..\..\src\rest.cpp" />
|
||||
<ClCompile Include="..\..\src\shutdown.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\blockchain.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\mining.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\misc.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\net.cpp">
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)\netrpc.obj</ObjectFileName>
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)\netrpc.obj</ObjectFileName>
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(IntDir)\netrpc.obj</ObjectFileName>
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(IntDir)\netrpc.obj</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\rpc\rawtransaction.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\server.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\util.cpp" />
|
||||
<ClCompile Include="..\..\src\script\ismine.cpp" />
|
||||
<ClCompile Include="..\..\src\script\sigcache.cpp" />
|
||||
<ClCompile Include="..\..\src\timedata.cpp" />
|
||||
<ClCompile Include="..\..\src\torcontrol.cpp" />
|
||||
<ClCompile Include="..\..\src\txdb.cpp" />
|
||||
<ClCompile Include="..\..\src\txmempool.cpp" />
|
||||
<ClCompile Include="..\..\src\ui_interface.cpp" />
|
||||
<ClCompile Include="..\..\src\validation.cpp" />
|
||||
<ClCompile Include="..\..\src\validationinterface.cpp" />
|
||||
<ClCompile Include="..\..\src\versionbits.cpp" />
|
||||
<ClCompile Include="..\..\src\index\txindex.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
@ -174,23 +174,7 @@
|
|||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\chainparamsbase.cpp" />
|
||||
<ClCompile Include="..\..\src\clientversion.cpp" />
|
||||
<ClCompile Include="..\..\src\compat\glibcxx_sanity.cpp" />
|
||||
<ClCompile Include="..\..\src\compat\glibc_sanity.cpp" />
|
||||
<ClCompile Include="..\..\src\compat\strnlen.cpp" />
|
||||
<ClCompile Include="..\..\src\fs.cpp" />
|
||||
<ClCompile Include="..\..\src\logging.cpp" />
|
||||
<ClCompile Include="..\..\src\random.cpp" />
|
||||
<ClCompile Include="..\..\src\rpc\protocol.cpp" />
|
||||
<ClCompile Include="..\..\src\support\cleanse.cpp" />
|
||||
<ClCompile Include="..\..\src\support\lockedpool.cpp" />
|
||||
<ClCompile Include="..\..\src\sync.cpp" />
|
||||
<ClCompile Include="..\..\src\threadinterrupt.cpp" />
|
||||
<ClCompile Include="..\..\src\util.cpp" />
|
||||
<ClCompile Include="..\..\src\utilmoneystr.cpp" />
|
||||
<ClCompile Include="..\..\src\utilstrencodings.cpp" />
|
||||
<ClCompile Include="..\..\src\utiltime.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<Import Label="configTarget" Project="..\common.vcxproj" />
|
||||
</Project>
|
||||
|
|
@ -20,18 +20,7 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\wallet\coinselection.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\coincontrol.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\crypter.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\db.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\feebumper.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\fees.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\init.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\rpcdump.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\rpcwallet.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\wallet.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\walletdb.cpp" />
|
||||
<ClCompile Include="..\..\src\wallet\walletutil.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
@ -20,10 +20,7 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\zmq\zmqabstractnotifier.cpp" />
|
||||
<ClCompile Include="..\..\src\zmq\zmqnotificationinterface.cpp" />
|
||||
<ClCompile Include="..\..\src\zmq\zmqpublishnotifier.cpp" />
|
||||
<ClCompile Include="..\..\src\zmq\zmqrpc.cpp" />
|
||||
@SOURCE_FILES@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\src;</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
|
|
@ -144,7 +144,7 @@
|
|||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\src;</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\src;</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
|
|
@ -184,7 +184,7 @@
|
|||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>false</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\src;</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<SuppressStartupBanner>false</SuppressStartupBanner>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
|
|
|
|||
63
build_msvc/msvc-autogen.py
Normal file
63
build_msvc/msvc-autogen.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
SOURCE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'src'))
|
||||
|
||||
libs = [
|
||||
'libbitcoin_cli',
|
||||
'libbitcoin_common',
|
||||
'libbitcoin_crypto',
|
||||
'libbitcoin_server',
|
||||
'libbitcoin_util',
|
||||
'libbitcoin_wallet',
|
||||
'libbitcoin_zmq',
|
||||
]
|
||||
|
||||
ignore_list = [
|
||||
'rpc/net.cpp',
|
||||
'interfaces/handler.cpp',
|
||||
'interfaces/node.cpp',
|
||||
'interfaces/wallet.cpp',
|
||||
]
|
||||
|
||||
lib_sources = {}
|
||||
|
||||
|
||||
def parse_makefile(makefile):
|
||||
with open(makefile, 'r', encoding='utf-8') as file:
|
||||
current_lib = ''
|
||||
for line in file.read().splitlines():
|
||||
if current_lib:
|
||||
source = line.split()[0]
|
||||
if source.endswith('.cpp') and not source.startswith('$') and source not in ignore_list:
|
||||
lib_sources[current_lib].append(source.replace('/', '\\'))
|
||||
if not line.endswith('\\'):
|
||||
current_lib = ''
|
||||
continue
|
||||
for lib in libs:
|
||||
_lib = lib.replace('-', '_')
|
||||
if re.search(_lib + '.*_SOURCES \\= \\\\', line):
|
||||
current_lib = lib
|
||||
lib_sources[current_lib] = []
|
||||
break
|
||||
|
||||
|
||||
def main():
|
||||
for makefile_name in os.listdir(SOURCE_DIR):
|
||||
if 'Makefile' in makefile_name:
|
||||
parse_makefile(os.path.join(SOURCE_DIR, makefile_name))
|
||||
for key, value in lib_sources.items():
|
||||
vcxproj_filename = os.path.abspath(os.path.join(os.path.dirname(__file__), key, key + '.vcxproj'))
|
||||
content = ''
|
||||
for source_filename in value:
|
||||
content += ' <ClCompile Include="..\\..\\src\\' + source_filename + '" />\n'
|
||||
with open(vcxproj_filename + '.in', 'r', encoding='utf-8') as vcxproj_in_file:
|
||||
with open(vcxproj_filename, 'w', encoding='utf-8') as vcxproj_file:
|
||||
vcxproj_file.write(vcxproj_in_file.read().replace(
|
||||
'@SOURCE_FILES@\n', content))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
26
configure.ac
26
configure.ac
|
|
@ -130,6 +130,12 @@ AC_ARG_ENABLE(gui-tests,
|
|||
[use_gui_tests=$enableval],
|
||||
[use_gui_tests=$use_tests])
|
||||
|
||||
AC_ARG_WITH([rapidcheck],
|
||||
[AS_HELP_STRING([--with-rapidcheck],
|
||||
[enable RapidCheck property based tests (default is yes if librapidcheck is found)])],
|
||||
[use_rapidcheck=$withval],
|
||||
[use_rapidcheck=auto])
|
||||
|
||||
AC_ARG_ENABLE(bench,
|
||||
AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
|
||||
[use_bench=$enableval],
|
||||
|
|
@ -727,6 +733,10 @@ fi
|
|||
|
||||
AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h sys/prctl.h])
|
||||
|
||||
AC_CHECK_DECLS([getifaddrs, freeifaddrs],,,
|
||||
[#include <sys/types.h>
|
||||
#include <ifaddrs.h>]
|
||||
)
|
||||
AC_CHECK_DECLS([strnlen])
|
||||
|
||||
# Check for daemon(3), unrelated to --with-daemon (although used by it)
|
||||
|
|
@ -1134,6 +1144,22 @@ AC_CHECK_DECLS([EVP_MD_CTX_new],,,[AC_INCLUDES_DEFAULT
|
|||
])
|
||||
CXXFLAGS="${save_CXXFLAGS}"
|
||||
|
||||
dnl RapidCheck Property Based Testing
|
||||
|
||||
enable_property_tests=no
|
||||
if test "x$use_rapidcheck" = xauto; then
|
||||
AC_CHECK_HEADERS([rapidcheck.h], [enable_property_tests=yes])
|
||||
elif test "x$use_rapidcheck" != xno; then
|
||||
enable_property_tests=yes
|
||||
fi
|
||||
|
||||
RAPIDCHECK_LIBS=
|
||||
if test "x$enable_property_tests" = xyes; then
|
||||
RAPIDCHECK_LIBS=-lrapidcheck
|
||||
fi
|
||||
AC_SUBST(RAPIDCHECK_LIBS)
|
||||
AM_CONDITIONAL([ENABLE_PROPERTY_TESTS], [test x$enable_property_tests = xyes])
|
||||
|
||||
dnl univalue check
|
||||
|
||||
need_bundled_univalue=yes
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ Comment: Site: https://bitcointalk.org/?topic=1756.0
|
|||
Files: src/qt/res/icons/proxy.png
|
||||
src/qt/res/src/proxy.svg
|
||||
Copyright: Cristian Mircea Messel
|
||||
Licese: public-domain
|
||||
License: public-domain
|
||||
|
||||
|
||||
License: Expat
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ def content_hash(filename):
|
|||
pngcrush = 'pngcrush'
|
||||
git = 'git'
|
||||
folders = ["src/qt/res/movies", "src/qt/res/icons", "share/pixmaps"]
|
||||
basePath = subprocess.check_output([git, 'rev-parse', '--show-toplevel'], universal_newlines=True).rstrip('\n')
|
||||
basePath = subprocess.check_output([git, 'rev-parse', '--show-toplevel'], universal_newlines=True, encoding='utf8').rstrip('\n')
|
||||
totalSaveBytes = 0
|
||||
noHashChange = True
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ for folder in folders:
|
|||
sys.exit(0)
|
||||
|
||||
#verify
|
||||
if "Not a PNG file" in subprocess.check_output([pngcrush, "-n", "-v", file_path], stderr=subprocess.STDOUT, universal_newlines=True):
|
||||
if "Not a PNG file" in subprocess.check_output([pngcrush, "-n", "-v", file_path], stderr=subprocess.STDOUT, universal_newlines=True, encoding='utf8'):
|
||||
print("PNG file "+file+" is corrupted after crushing, check out pngcursh version")
|
||||
sys.exit(1)
|
||||
|
||||
|
|
|
|||
|
|
@ -36,17 +36,18 @@ import os
|
|||
# (glibc) GLIBC_2_11
|
||||
#
|
||||
MAX_VERSIONS = {
|
||||
'GCC': (4,4,0),
|
||||
'CXXABI': (1,3,3),
|
||||
'GLIBCXX': (3,4,13),
|
||||
'GLIBC': (2,11)
|
||||
'GCC': (4,4,0),
|
||||
'CXXABI': (1,3,3),
|
||||
'GLIBCXX': (3,4,13),
|
||||
'GLIBC': (2,11),
|
||||
'LIBATOMIC': (1,0)
|
||||
}
|
||||
# See here for a description of _IO_stdin_used:
|
||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109
|
||||
|
||||
# Ignore symbols that are exported as part of every executable
|
||||
IGNORE_EXPORTS = {
|
||||
'_edata', '_end', '_init', '__bss_start', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr'
|
||||
'_edata', '_end', '__end__', '_init', '__bss_start', '__bss_start__', '_bss_end__', '__bss_end__', '_fini', '_IO_stdin_used', 'stdin', 'stdout', 'stderr'
|
||||
}
|
||||
READELF_CMD = os.getenv('READELF', '/usr/bin/readelf')
|
||||
CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt')
|
||||
|
|
@ -59,8 +60,12 @@ ALLOWED_LIBRARIES = {
|
|||
'libanl.so.1', # DNS resolve
|
||||
'libm.so.6', # math library
|
||||
'librt.so.1', # real-time (clock)
|
||||
'libatomic.so.1',
|
||||
'ld-linux-x86-64.so.2', # 64-bit dynamic linker
|
||||
'ld-linux.so.2', # 32-bit dynamic linker
|
||||
'ld-linux-aarch64.so.1', # 64-bit ARM dynamic linker
|
||||
'ld-linux-armhf.so.3', # 32-bit ARM dynamic linker
|
||||
'ld-linux-riscv64-lp64d.so.1', # 64-bit RISC-V dynamic linker
|
||||
# bitcoin-qt only
|
||||
'libX11-xcb.so.1', # part of X11
|
||||
'libX11.so.6', # part of X11
|
||||
|
|
@ -69,7 +74,13 @@ ALLOWED_LIBRARIES = {
|
|||
'libfreetype.so.6', # font parsing
|
||||
'libdl.so.2' # programming interface to dynamic linker
|
||||
}
|
||||
|
||||
ARCH_MIN_GLIBC_VER = {
|
||||
'80386': (2,1),
|
||||
'X86-64': (2,2,5),
|
||||
'ARM': (2,4),
|
||||
'AArch64':(2,17),
|
||||
'RISC-V': (2,27)
|
||||
}
|
||||
class CPPFilt(object):
|
||||
'''
|
||||
Demangle C++ symbol names.
|
||||
|
|
@ -94,23 +105,25 @@ def read_symbols(executable, imports=True):
|
|||
Parse an ELF executable and return a list of (symbol,version) tuples
|
||||
for dynamic, imported symbols.
|
||||
'''
|
||||
p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
|
||||
p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', '-h', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
|
||||
(stdout, stderr) = p.communicate()
|
||||
if p.returncode:
|
||||
raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip()))
|
||||
syms = []
|
||||
for line in stdout.splitlines():
|
||||
line = line.split()
|
||||
if 'Machine:' in line:
|
||||
arch = line[-1]
|
||||
if len(line)>7 and re.match('[0-9]+:$', line[0]):
|
||||
(sym, _, version) = line[7].partition('@')
|
||||
is_import = line[6] == 'UND'
|
||||
if version.startswith('@'):
|
||||
version = version[1:]
|
||||
if is_import == imports:
|
||||
syms.append((sym, version))
|
||||
syms.append((sym, version, arch))
|
||||
return syms
|
||||
|
||||
def check_version(max_versions, version):
|
||||
def check_version(max_versions, version, arch):
|
||||
if '_' in version:
|
||||
(lib, _, ver) = version.rpartition('_')
|
||||
else:
|
||||
|
|
@ -119,7 +132,7 @@ def check_version(max_versions, version):
|
|||
ver = tuple([int(x) for x in ver.split('.')])
|
||||
if not lib in max_versions:
|
||||
return False
|
||||
return ver <= max_versions[lib]
|
||||
return ver <= max_versions[lib] or lib == 'GLIBC' and ver <= ARCH_MIN_GLIBC_VER[arch]
|
||||
|
||||
def read_libraries(filename):
|
||||
p = subprocess.Popen([READELF_CMD, '-d', '-W', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True)
|
||||
|
|
@ -142,16 +155,17 @@ if __name__ == '__main__':
|
|||
retval = 0
|
||||
for filename in sys.argv[1:]:
|
||||
# Check imported symbols
|
||||
for sym,version in read_symbols(filename, True):
|
||||
if version and not check_version(MAX_VERSIONS, version):
|
||||
for sym,version,arch in read_symbols(filename, True):
|
||||
if version and not check_version(MAX_VERSIONS, version, arch):
|
||||
print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version))
|
||||
retval = 1
|
||||
# Check exported symbols
|
||||
for sym,version in read_symbols(filename, False):
|
||||
if sym in IGNORE_EXPORTS:
|
||||
continue
|
||||
print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym)))
|
||||
retval = 1
|
||||
if arch != 'RISC-V':
|
||||
for sym,version,arch in read_symbols(filename, False):
|
||||
if sym in IGNORE_EXPORTS:
|
||||
continue
|
||||
print('%s: export of symbol %s not allowed' % (filename, cppfilt(sym)))
|
||||
retval = 1
|
||||
# Check dependency libraries
|
||||
for library_name in read_libraries(filename):
|
||||
if library_name not in ALLOWED_LIBRARIES:
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ def main():
|
|||
|
||||
parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version')
|
||||
parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch')
|
||||
parser.add_argument('-p', '--pull', action='store_true', dest='pull', help='Indicate that the version argument is the number of a github repository pull request')
|
||||
parser.add_argument('-u', '--url', dest='url', default='https://github.com/bitcoin/bitcoin', help='Specify the URL of the repository. Default is %(default)s')
|
||||
parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build')
|
||||
parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build')
|
||||
|
|
@ -169,7 +170,7 @@ def main():
|
|||
|
||||
args.sign_prog = 'true' if args.detach_sign else 'gpg --detach-sign'
|
||||
|
||||
# Set enviroment variable USE_LXC or USE_DOCKER, let gitian-builder know that we use lxc or docker
|
||||
# Set environment variable USE_LXC or USE_DOCKER, let gitian-builder know that we use lxc or docker
|
||||
if args.docker:
|
||||
os.environ['USE_DOCKER'] = '1'
|
||||
elif not args.kvm:
|
||||
|
|
@ -196,13 +197,21 @@ def main():
|
|||
exit(1)
|
||||
|
||||
# Add leading 'v' for tags
|
||||
if args.commit and args.pull:
|
||||
raise Exception('Cannot have both commit and pull')
|
||||
args.commit = ('' if args.commit else 'v') + args.version
|
||||
print(args.commit)
|
||||
|
||||
if args.setup:
|
||||
setup()
|
||||
|
||||
os.chdir('bitcoin')
|
||||
if args.pull:
|
||||
subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge'])
|
||||
os.chdir('../gitian-builder/inputs/bitcoin')
|
||||
subprocess.check_call(['git', 'fetch', args.url, 'refs/pull/'+args.version+'/merge'])
|
||||
args.commit = subprocess.check_output(['git', 'show', '-s', '--format=%H', 'FETCH_HEAD'], universal_newlines=True, encoding='utf8').strip()
|
||||
args.version = 'pull-' + args.version
|
||||
print(args.commit)
|
||||
subprocess.check_call(['git', 'fetch'])
|
||||
subprocess.check_call(['git', 'checkout', args.commit])
|
||||
os.chdir(workdir)
|
||||
|
|
|
|||
|
|
@ -173,18 +173,7 @@ script: |
|
|||
CONFIG_SITE=${BASEPREFIX}/${i}/share/config.site ./configure --prefix=/ --disable-ccache --disable-maintainer-mode --disable-dependency-tracking ${CONFIGFLAGS} CFLAGS="${HOST_CFLAGS}" CXXFLAGS="${HOST_CXXFLAGS}" LDFLAGS="${HOST_LDFLAGS}"
|
||||
make ${MAKEOPTS}
|
||||
make ${MAKEOPTS} -C src check-security
|
||||
|
||||
#TODO: This is a quick hack that disables symbol checking for arm.
|
||||
# Instead, we should investigate why these are popping up.
|
||||
# For aarch64, we'll need to bump up the min GLIBC version, as the abi
|
||||
# support wasn't introduced until 2.17.
|
||||
case $i in
|
||||
aarch64-*) : ;;
|
||||
arm-*) : ;;
|
||||
riscv64-*) : ;;
|
||||
*) make ${MAKEOPTS} -C src check-symbols ;;
|
||||
esac
|
||||
|
||||
make ${MAKEOPTS} -C src check-symbols
|
||||
make install DESTDIR=${INSTALLPATH}
|
||||
cd installed
|
||||
find . -name "lib*.la" -delete
|
||||
|
|
@ -192,6 +181,7 @@ script: |
|
|||
rm -rf ${DISTNAME}/lib/pkgconfig
|
||||
find ${DISTNAME}/bin -type f -executable -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \;
|
||||
find ${DISTNAME}/lib -type f -exec ../contrib/devtools/split-debug.sh {} {} {}.dbg \;
|
||||
cp ../doc/README.md ${DISTNAME}/
|
||||
find ${DISTNAME} -not -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}.tar.gz
|
||||
find ${DISTNAME} -name "*.dbg" | sort | tar --no-recursion --mode='u+rw,go+r-w,a+X' --owner=0 --group=0 -c -T - | gzip -9n > ${OUTDIR}/${DISTNAME}-${i}-debug.tar.gz
|
||||
cd ../../
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ Utilities to generate test vectors for the data-driven Bitcoin tests.
|
|||
|
||||
Usage:
|
||||
|
||||
gen_base58_test_vectors.py valid 50 > ../../src/test/data/base58_keys_valid.json
|
||||
gen_base58_test_vectors.py invalid 50 > ../../src/test/data/base58_keys_invalid.json
|
||||
PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_keys_valid.json
|
||||
PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_keys_invalid.json
|
||||
|
|
|
|||
|
|
@ -1,132 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2012-2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Generate valid and invalid base58 address and private key test vectors.
|
||||
|
||||
Usage:
|
||||
gen_base58_test_vectors.py valid 50 > ../../src/test/data/base58_keys_valid.json
|
||||
gen_base58_test_vectors.py invalid 50 > ../../src/test/data/base58_keys_invalid.json
|
||||
'''
|
||||
# 2012 Wladimir J. van der Laan
|
||||
# Released under MIT License
|
||||
import os
|
||||
from itertools import islice
|
||||
from base58 import b58encode_chk, b58decode_chk, b58chars
|
||||
import random
|
||||
from binascii import b2a_hex
|
||||
|
||||
# key types
|
||||
PUBKEY_ADDRESS = 0
|
||||
SCRIPT_ADDRESS = 5
|
||||
PUBKEY_ADDRESS_TEST = 111
|
||||
SCRIPT_ADDRESS_TEST = 196
|
||||
PRIVKEY = 128
|
||||
PRIVKEY_TEST = 239
|
||||
|
||||
metadata_keys = ['isPrivkey', 'isTestnet', 'addrType', 'isCompressed']
|
||||
# templates for valid sequences
|
||||
templates = [
|
||||
# prefix, payload_size, suffix, metadata
|
||||
# None = N/A
|
||||
((PUBKEY_ADDRESS,), 20, (), (False, False, 'pubkey', None)),
|
||||
((SCRIPT_ADDRESS,), 20, (), (False, False, 'script', None)),
|
||||
((PUBKEY_ADDRESS_TEST,), 20, (), (False, True, 'pubkey', None)),
|
||||
((SCRIPT_ADDRESS_TEST,), 20, (), (False, True, 'script', None)),
|
||||
((PRIVKEY,), 32, (), (True, False, None, False)),
|
||||
((PRIVKEY,), 32, (1,), (True, False, None, True)),
|
||||
((PRIVKEY_TEST,), 32, (), (True, True, None, False)),
|
||||
((PRIVKEY_TEST,), 32, (1,), (True, True, None, True))
|
||||
]
|
||||
|
||||
def is_valid(v):
|
||||
'''Check vector v for validity'''
|
||||
result = b58decode_chk(v)
|
||||
if result is None:
|
||||
return False
|
||||
for template in templates:
|
||||
prefix = bytearray(template[0])
|
||||
suffix = bytearray(template[2])
|
||||
if result.startswith(prefix) and result.endswith(suffix):
|
||||
if (len(result) - len(prefix) - len(suffix)) == template[1]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def gen_valid_vectors():
|
||||
'''Generate valid test vectors'''
|
||||
while True:
|
||||
for template in templates:
|
||||
prefix = bytearray(template[0])
|
||||
payload = bytearray(os.urandom(template[1]))
|
||||
suffix = bytearray(template[2])
|
||||
rv = b58encode_chk(prefix + payload + suffix)
|
||||
assert is_valid(rv)
|
||||
metadata = {x: y for x, y in zip(metadata_keys,template[3]) if y is not None}
|
||||
hexrepr = b2a_hex(payload)
|
||||
if isinstance(hexrepr, bytes):
|
||||
hexrepr = hexrepr.decode('utf8')
|
||||
yield (rv, hexrepr, metadata)
|
||||
|
||||
def gen_invalid_vector(template, corrupt_prefix, randomize_payload_size, corrupt_suffix):
|
||||
'''Generate possibly invalid vector'''
|
||||
if corrupt_prefix:
|
||||
prefix = os.urandom(1)
|
||||
else:
|
||||
prefix = bytearray(template[0])
|
||||
|
||||
if randomize_payload_size:
|
||||
payload = os.urandom(max(int(random.expovariate(0.5)), 50))
|
||||
else:
|
||||
payload = os.urandom(template[1])
|
||||
|
||||
if corrupt_suffix:
|
||||
suffix = os.urandom(len(template[2]))
|
||||
else:
|
||||
suffix = bytearray(template[2])
|
||||
|
||||
return b58encode_chk(prefix + payload + suffix)
|
||||
|
||||
def randbool(p = 0.5):
|
||||
'''Return True with P(p)'''
|
||||
return random.random() < p
|
||||
|
||||
def gen_invalid_vectors():
|
||||
'''Generate invalid test vectors'''
|
||||
# start with some manual edge-cases
|
||||
yield "",
|
||||
yield "x",
|
||||
while True:
|
||||
# kinds of invalid vectors:
|
||||
# invalid prefix
|
||||
# invalid payload length
|
||||
# invalid (randomized) suffix (add random data)
|
||||
# corrupt checksum
|
||||
for template in templates:
|
||||
val = gen_invalid_vector(template, randbool(0.2), randbool(0.2), randbool(0.2))
|
||||
if random.randint(0,10)<1: # line corruption
|
||||
if randbool(): # add random character to end
|
||||
val += random.choice(b58chars)
|
||||
else: # replace random character in the middle
|
||||
n = random.randint(0, len(val))
|
||||
val = val[0:n] + random.choice(b58chars) + val[n+1:]
|
||||
if not is_valid(val):
|
||||
yield val,
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import json
|
||||
iters = {'valid':gen_valid_vectors, 'invalid':gen_invalid_vectors}
|
||||
try:
|
||||
uiter = iters[sys.argv[1]]
|
||||
except IndexError:
|
||||
uiter = gen_valid_vectors
|
||||
try:
|
||||
count = int(sys.argv[2])
|
||||
except IndexError:
|
||||
count = 0
|
||||
|
||||
data = list(islice(uiter(), count))
|
||||
json.dump(data, sys.stdout, sort_keys=True, indent=4)
|
||||
sys.stdout.write('\n')
|
||||
|
||||
249
contrib/testgen/gen_key_io_test_vectors.py
Executable file
249
contrib/testgen/gen_key_io_test_vectors.py
Executable file
|
|
@ -0,0 +1,249 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2012-2018 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
'''
|
||||
Generate valid and invalid base58 address and private key test vectors.
|
||||
|
||||
Usage:
|
||||
PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py valid 50 > ../../src/test/data/key_io_valid.json
|
||||
PYTHONPATH=../../test/functional/test_framework ./gen_key_io_test_vectors.py invalid 50 > ../../src/test/data/key_io_invalid.json
|
||||
'''
|
||||
# 2012 Wladimir J. van der Laan
|
||||
# Released under MIT License
|
||||
import os
|
||||
from itertools import islice
|
||||
from base58 import b58encode_chk, b58decode_chk, b58chars
|
||||
import random
|
||||
from binascii import b2a_hex
|
||||
from segwit_addr import bech32_encode, decode, convertbits, CHARSET
|
||||
|
||||
# key types
|
||||
PUBKEY_ADDRESS = 0
|
||||
SCRIPT_ADDRESS = 5
|
||||
PUBKEY_ADDRESS_TEST = 111
|
||||
SCRIPT_ADDRESS_TEST = 196
|
||||
PUBKEY_ADDRESS_REGTEST = 111
|
||||
SCRIPT_ADDRESS_REGTEST = 196
|
||||
PRIVKEY = 128
|
||||
PRIVKEY_TEST = 239
|
||||
PRIVKEY_REGTEST = 239
|
||||
|
||||
# script
|
||||
OP_0 = 0x00
|
||||
OP_1 = 0x51
|
||||
OP_2 = 0x52
|
||||
OP_16 = 0x60
|
||||
OP_DUP = 0x76
|
||||
OP_EQUAL = 0x87
|
||||
OP_EQUALVERIFY = 0x88
|
||||
OP_HASH160 = 0xa9
|
||||
OP_CHECKSIG = 0xac
|
||||
pubkey_prefix = (OP_DUP, OP_HASH160, 20)
|
||||
pubkey_suffix = (OP_EQUALVERIFY, OP_CHECKSIG)
|
||||
script_prefix = (OP_HASH160, 20)
|
||||
script_suffix = (OP_EQUAL,)
|
||||
p2wpkh_prefix = (OP_0, 20)
|
||||
p2wsh_prefix = (OP_0, 32)
|
||||
|
||||
metadata_keys = ['isPrivkey', 'chain', 'isCompressed', 'tryCaseFlip']
|
||||
# templates for valid sequences
|
||||
templates = [
|
||||
# prefix, payload_size, suffix, metadata, output_prefix, output_suffix
|
||||
# None = N/A
|
||||
((PUBKEY_ADDRESS,), 20, (), (False, 'main', None, None), pubkey_prefix, pubkey_suffix),
|
||||
((SCRIPT_ADDRESS,), 20, (), (False, 'main', None, None), script_prefix, script_suffix),
|
||||
((PUBKEY_ADDRESS_TEST,), 20, (), (False, 'test', None, None), pubkey_prefix, pubkey_suffix),
|
||||
((SCRIPT_ADDRESS_TEST,), 20, (), (False, 'test', None, None), script_prefix, script_suffix),
|
||||
((PUBKEY_ADDRESS_REGTEST,), 20, (), (False, 'regtest', None, None), pubkey_prefix, pubkey_suffix),
|
||||
((SCRIPT_ADDRESS_REGTEST,), 20, (), (False, 'regtest', None, None), script_prefix, script_suffix),
|
||||
((PRIVKEY,), 32, (), (True, 'main', False, None), (), ()),
|
||||
((PRIVKEY,), 32, (1,), (True, 'main', True, None), (), ()),
|
||||
((PRIVKEY_TEST,), 32, (), (True, 'test', False, None), (), ()),
|
||||
((PRIVKEY_TEST,), 32, (1,), (True, 'test', True, None), (), ()),
|
||||
((PRIVKEY_REGTEST,), 32, (), (True, 'regtest', False, None), (), ()),
|
||||
((PRIVKEY_REGTEST,), 32, (1,), (True, 'regtest', True, None), (), ())
|
||||
]
|
||||
# templates for valid bech32 sequences
|
||||
bech32_templates = [
|
||||
# hrp, version, witprog_size, metadata, output_prefix
|
||||
('bc', 0, 20, (False, 'main', None, True), p2wpkh_prefix),
|
||||
('bc', 0, 32, (False, 'main', None, True), p2wsh_prefix),
|
||||
('bc', 1, 2, (False, 'main', None, True), (OP_1, 2)),
|
||||
('tb', 0, 20, (False, 'test', None, True), p2wpkh_prefix),
|
||||
('tb', 0, 32, (False, 'test', None, True), p2wsh_prefix),
|
||||
('tb', 2, 16, (False, 'test', None, True), (OP_2, 16)),
|
||||
('bcrt', 0, 20, (False, 'regtest', None, True), p2wpkh_prefix),
|
||||
('bcrt', 0, 32, (False, 'regtest', None, True), p2wsh_prefix),
|
||||
('bcrt', 16, 40, (False, 'regtest', None, True), (OP_16, 40))
|
||||
]
|
||||
# templates for invalid bech32 sequences
|
||||
bech32_ng_templates = [
|
||||
# hrp, version, witprog_size, invalid_bech32, invalid_checksum, invalid_char
|
||||
('tc', 0, 20, False, False, False),
|
||||
('tb', 17, 32, False, False, False),
|
||||
('bcrt', 3, 1, False, False, False),
|
||||
('bc', 15, 41, False, False, False),
|
||||
('tb', 0, 16, False, False, False),
|
||||
('bcrt', 0, 32, True, False, False),
|
||||
('bc', 0, 16, True, False, False),
|
||||
('tb', 0, 32, False, True, False),
|
||||
('bcrt', 0, 20, False, False, True)
|
||||
]
|
||||
|
||||
def is_valid(v):
|
||||
'''Check vector v for validity'''
|
||||
if len(set(v) - set(b58chars)) > 0:
|
||||
return is_valid_bech32(v)
|
||||
result = b58decode_chk(v)
|
||||
if result is None:
|
||||
return is_valid_bech32(v)
|
||||
for template in templates:
|
||||
prefix = bytearray(template[0])
|
||||
suffix = bytearray(template[2])
|
||||
if result.startswith(prefix) and result.endswith(suffix):
|
||||
if (len(result) - len(prefix) - len(suffix)) == template[1]:
|
||||
return True
|
||||
return is_valid_bech32(v)
|
||||
|
||||
def is_valid_bech32(v):
|
||||
'''Check vector v for bech32 validity'''
|
||||
for hrp in ['bc', 'tb', 'bcrt']:
|
||||
if decode(hrp, v) != (None, None):
|
||||
return True
|
||||
return False
|
||||
|
||||
def gen_valid_base58_vector(template):
|
||||
'''Generate valid base58 vector'''
|
||||
prefix = bytearray(template[0])
|
||||
payload = bytearray(os.urandom(template[1]))
|
||||
suffix = bytearray(template[2])
|
||||
dst_prefix = bytearray(template[4])
|
||||
dst_suffix = bytearray(template[5])
|
||||
rv = b58encode_chk(prefix + payload + suffix)
|
||||
return rv, dst_prefix + payload + dst_suffix
|
||||
|
||||
def gen_valid_bech32_vector(template):
|
||||
'''Generate valid bech32 vector'''
|
||||
hrp = template[0]
|
||||
witver = template[1]
|
||||
witprog = bytearray(os.urandom(template[2]))
|
||||
dst_prefix = bytearray(template[4])
|
||||
rv = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5))
|
||||
return rv, dst_prefix + witprog
|
||||
|
||||
def gen_valid_vectors():
|
||||
'''Generate valid test vectors'''
|
||||
glist = [gen_valid_base58_vector, gen_valid_bech32_vector]
|
||||
tlist = [templates, bech32_templates]
|
||||
while True:
|
||||
for template, valid_vector_generator in [(t, g) for g, l in zip(glist, tlist) for t in l]:
|
||||
rv, payload = valid_vector_generator(template)
|
||||
assert is_valid(rv)
|
||||
metadata = {x: y for x, y in zip(metadata_keys,template[3]) if y is not None}
|
||||
hexrepr = b2a_hex(payload)
|
||||
if isinstance(hexrepr, bytes):
|
||||
hexrepr = hexrepr.decode('utf8')
|
||||
yield (rv, hexrepr, metadata)
|
||||
|
||||
def gen_invalid_base58_vector(template):
|
||||
'''Generate possibly invalid vector'''
|
||||
# kinds of invalid vectors:
|
||||
# invalid prefix
|
||||
# invalid payload length
|
||||
# invalid (randomized) suffix (add random data)
|
||||
# corrupt checksum
|
||||
corrupt_prefix = randbool(0.2)
|
||||
randomize_payload_size = randbool(0.2)
|
||||
corrupt_suffix = randbool(0.2)
|
||||
|
||||
if corrupt_prefix:
|
||||
prefix = os.urandom(1)
|
||||
else:
|
||||
prefix = bytearray(template[0])
|
||||
|
||||
if randomize_payload_size:
|
||||
payload = os.urandom(max(int(random.expovariate(0.5)), 50))
|
||||
else:
|
||||
payload = os.urandom(template[1])
|
||||
|
||||
if corrupt_suffix:
|
||||
suffix = os.urandom(len(template[2]))
|
||||
else:
|
||||
suffix = bytearray(template[2])
|
||||
|
||||
val = b58encode_chk(prefix + payload + suffix)
|
||||
if random.randint(0,10)<1: # line corruption
|
||||
if randbool(): # add random character to end
|
||||
val += random.choice(b58chars)
|
||||
else: # replace random character in the middle
|
||||
n = random.randint(0, len(val))
|
||||
val = val[0:n] + random.choice(b58chars) + val[n+1:]
|
||||
|
||||
return val
|
||||
|
||||
def gen_invalid_bech32_vector(template):
|
||||
'''Generate possibly invalid bech32 vector'''
|
||||
no_data = randbool(0.1)
|
||||
to_upper = randbool(0.1)
|
||||
hrp = template[0]
|
||||
witver = template[1]
|
||||
witprog = bytearray(os.urandom(template[2]))
|
||||
|
||||
if no_data:
|
||||
rv = bech32_encode(hrp, [])
|
||||
else:
|
||||
data = [witver] + convertbits(witprog, 8, 5)
|
||||
if template[3] and not no_data:
|
||||
if template[2] % 5 in {2, 4}:
|
||||
data[-1] |= 1
|
||||
else:
|
||||
data.append(0)
|
||||
rv = bech32_encode(hrp, data)
|
||||
|
||||
if template[4]:
|
||||
i = len(rv) - random.randrange(1, 7)
|
||||
rv = rv[:i] + random.choice(CHARSET.replace(rv[i], '')) + rv[i + 1:]
|
||||
if template[5]:
|
||||
i = len(hrp) + 1 + random.randrange(0, len(rv) - len(hrp) - 4)
|
||||
rv = rv[:i] + rv[i:i + 4].upper() + rv[i + 4:]
|
||||
|
||||
if to_upper:
|
||||
rv = rv.swapcase()
|
||||
|
||||
return rv
|
||||
|
||||
def randbool(p = 0.5):
|
||||
'''Return True with P(p)'''
|
||||
return random.random() < p
|
||||
|
||||
def gen_invalid_vectors():
|
||||
'''Generate invalid test vectors'''
|
||||
# start with some manual edge-cases
|
||||
yield "",
|
||||
yield "x",
|
||||
glist = [gen_invalid_base58_vector, gen_invalid_bech32_vector]
|
||||
tlist = [templates, bech32_ng_templates]
|
||||
while True:
|
||||
for template, invalid_vector_generator in [(t, g) for g, l in zip(glist, tlist) for t in l]:
|
||||
val = invalid_vector_generator(template)
|
||||
if not is_valid(val):
|
||||
yield val,
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import json
|
||||
iters = {'valid':gen_valid_vectors, 'invalid':gen_invalid_vectors}
|
||||
try:
|
||||
uiter = iters[sys.argv[1]]
|
||||
except IndexError:
|
||||
uiter = gen_valid_vectors
|
||||
try:
|
||||
count = int(sys.argv[2])
|
||||
except IndexError:
|
||||
count = 0
|
||||
|
||||
data = list(islice(uiter(), count))
|
||||
json.dump(data, sys.stdout, sort_keys=True, indent=4)
|
||||
sys.stdout.write('\n')
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ def main():
|
|||
no_sha1 = True
|
||||
prev_commit = ""
|
||||
initial_commit = current_commit
|
||||
branch = subprocess.check_output([GIT, 'show', '-s', '--format=%H', initial_commit], universal_newlines=True).splitlines()[0]
|
||||
branch = subprocess.check_output([GIT, 'show', '-s', '--format=%H', initial_commit], universal_newlines=True, encoding='utf8').splitlines()[0]
|
||||
|
||||
# Iterate through commits
|
||||
while True:
|
||||
|
|
@ -112,7 +112,7 @@ def main():
|
|||
if prev_commit != "":
|
||||
print("No parent of {} was signed with a trusted key!".format(prev_commit), file=sys.stderr)
|
||||
print("Parents are:", file=sys.stderr)
|
||||
parents = subprocess.check_output([GIT, 'show', '-s', '--format=format:%P', prev_commit], universal_newlines=True).splitlines()[0].split(' ')
|
||||
parents = subprocess.check_output([GIT, 'show', '-s', '--format=format:%P', prev_commit], universal_newlines=True, encoding='utf8').splitlines()[0].split(' ')
|
||||
for parent in parents:
|
||||
subprocess.call([GIT, 'show', '-s', parent], stdout=sys.stderr)
|
||||
else:
|
||||
|
|
@ -122,25 +122,25 @@ def main():
|
|||
# Check the Tree-SHA512
|
||||
if (verify_tree or prev_commit == "") and current_commit not in incorrect_sha512_allowed:
|
||||
tree_hash = tree_sha512sum(current_commit)
|
||||
if ("Tree-SHA512: {}".format(tree_hash)) not in subprocess.check_output([GIT, 'show', '-s', '--format=format:%B', current_commit], universal_newlines=True).splitlines():
|
||||
if ("Tree-SHA512: {}".format(tree_hash)) not in subprocess.check_output([GIT, 'show', '-s', '--format=format:%B', current_commit], universal_newlines=True, encoding='utf8').splitlines():
|
||||
print("Tree-SHA512 did not match for commit " + current_commit, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Merge commits should only have two parents
|
||||
parents = subprocess.check_output([GIT, 'show', '-s', '--format=format:%P', current_commit], universal_newlines=True).splitlines()[0].split(' ')
|
||||
parents = subprocess.check_output([GIT, 'show', '-s', '--format=format:%P', current_commit], universal_newlines=True, encoding='utf8').splitlines()[0].split(' ')
|
||||
if len(parents) > 2:
|
||||
print("Commit {} is an octopus merge".format(current_commit), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Check that the merge commit is clean
|
||||
commit_time = int(subprocess.check_output([GIT, 'show', '-s', '--format=format:%ct', current_commit], universal_newlines=True).splitlines()[0])
|
||||
commit_time = int(subprocess.check_output([GIT, 'show', '-s', '--format=format:%ct', current_commit], universal_newlines=True, encoding='utf8').splitlines()[0])
|
||||
check_merge = commit_time > time.time() - args.clean_merge * 24 * 60 * 60 # Only check commits in clean_merge days
|
||||
allow_unclean = current_commit in unclean_merge_allowed
|
||||
if len(parents) == 2 and check_merge and not allow_unclean:
|
||||
current_tree = subprocess.check_output([GIT, 'show', '--format=%T', current_commit], universal_newlines=True).splitlines()[0]
|
||||
current_tree = subprocess.check_output([GIT, 'show', '--format=%T', current_commit], universal_newlines=True, encoding='utf8').splitlines()[0]
|
||||
subprocess.call([GIT, 'checkout', '--force', '--quiet', parents[0]])
|
||||
subprocess.call([GIT, 'merge', '--no-ff', '--quiet', parents[1]], stdout=subprocess.DEVNULL)
|
||||
recreated_tree = subprocess.check_output([GIT, 'show', '--format=format:%T', 'HEAD'], universal_newlines=True).splitlines()[0]
|
||||
recreated_tree = subprocess.check_output([GIT, 'show', '--format=format:%T', 'HEAD'], universal_newlines=True, encoding='utf8').splitlines()[0]
|
||||
if current_tree != recreated_tree:
|
||||
print("Merge commit {} is not clean".format(current_commit), file=sys.stderr)
|
||||
subprocess.call([GIT, 'diff', current_commit])
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ WORK_PATH = $(BASEDIR)/work
|
|||
BASE_CACHE ?= $(BASEDIR)/built
|
||||
SDK_PATH ?= $(BASEDIR)/SDKs
|
||||
NO_QT ?=
|
||||
RAPIDCHECK ?=
|
||||
NO_WALLET ?=
|
||||
NO_UPNP ?=
|
||||
FALLBACK_DOWNLOAD_PATH ?= https://bitcoincore.org/depends-sources
|
||||
|
|
@ -14,7 +15,7 @@ HOST ?= $(BUILD)
|
|||
PATCHES_PATH = $(BASEDIR)/patches
|
||||
BASEDIR = $(CURDIR)
|
||||
HASH_LENGTH:=11
|
||||
DOWNLOAD_CONNECT_TIMEOUT:=10
|
||||
DOWNLOAD_CONNECT_TIMEOUT:=30
|
||||
DOWNLOAD_RETRIES:=3
|
||||
HOST_ID_SALT ?= salt
|
||||
BUILD_ID_SALT ?= salt
|
||||
|
|
@ -93,6 +94,8 @@ qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch
|
|||
wallet_packages_$(NO_WALLET) = $(wallet_packages)
|
||||
upnp_packages_$(NO_UPNP) = $(upnp_packages)
|
||||
|
||||
rapidcheck_packages_$(RAPIDCHECK) = $(rapidcheck_packages)
|
||||
|
||||
packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(wallet_packages_) $(upnp_packages_)
|
||||
native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages)
|
||||
|
||||
|
|
@ -100,6 +103,10 @@ ifneq ($(qt_packages_),)
|
|||
native_packages += $(qt_native_packages)
|
||||
endif
|
||||
|
||||
ifeq ($(rapidcheck_packages_),)
|
||||
packages += $(rapidcheck_packages)
|
||||
endif
|
||||
|
||||
all_packages = $(packages) $(native_packages)
|
||||
|
||||
meta_depends = Makefile funcs.mk builders/default.mk hosts/default.mk hosts/$(host_os).mk builders/$(build_os).mk
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ The following can be set when running make: make FOO=bar
|
|||
NO_WALLET: Don't download/build/cache libs needed to enable the wallet
|
||||
NO_UPNP: Don't download/build/cache packages needed for enabling upnp
|
||||
DEBUG: disable some optimizations and enable more runtime checking
|
||||
RAPIDCHECK: build rapidcheck (experimental)
|
||||
HOST_ID_SALT: Optional salt to use when generating host package ids
|
||||
BUILD_ID_SALT: Optional salt to use when generating build package ids
|
||||
|
||||
|
|
|
|||
|
|
@ -61,9 +61,12 @@ fi
|
|||
CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS"
|
||||
LDFLAGS="-L$depends_prefix/lib $LDFLAGS"
|
||||
|
||||
CC="@CC@"
|
||||
CXX="@CXX@"
|
||||
OBJC="${CC}"
|
||||
if test -n "@CC@" -a -z "${CC}"; then
|
||||
CC="@CC@"
|
||||
fi
|
||||
if test -n "@CXX@" -a -z "${CXX}"; then
|
||||
CXX="@CXX@"
|
||||
fi
|
||||
PYTHONPATH=$depends_prefix/native/lib/python/dist-packages:$PYTHONPATH
|
||||
|
||||
if test -n "@AR@"; then
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
package=libICE
|
||||
$(package)_version=1.0.9
|
||||
$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=8f7032f2c1c64352b5423f6b48a8ebdc339cc63064af34d66a6c9aa79759e202
|
||||
$(package)_dependencies=xtrans xproto
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--disable-static --disable-docs --disable-specs --without-xsltproc
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
$($(package)_autoconf)
|
||||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE)
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||
endef
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
package=libSM
|
||||
$(package)_version=1.2.2
|
||||
$(package)_download_path=http://xorg.freedesktop.org/releases/individual/lib/
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=0baca8c9f5d934450a70896c4ad38d06475521255ca63b717a6510fdb6e287bd
|
||||
$(package)_dependencies=xtrans xproto libICE
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--without-libuuid --without-xsltproc --disable-docs --disable-static
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
$($(package)_autoconf)
|
||||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE)
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||
endef
|
||||
|
|
@ -5,6 +5,8 @@ qt_packages = qrencode protobuf zlib
|
|||
|
||||
qt_linux_packages:=qt expat dbus libxcb xcb_proto libXau xproto freetype fontconfig libX11 xextproto libXext xtrans
|
||||
|
||||
rapidcheck_packages = rapidcheck
|
||||
|
||||
qt_darwin_packages=qt
|
||||
qt_mingw32_packages=qt
|
||||
|
||||
|
|
|
|||
18
depends/packages/rapidcheck.mk
Normal file
18
depends/packages/rapidcheck.mk
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package=rapidcheck
|
||||
$(package)_version=10fc0cb
|
||||
$(package)_download_path=https://github.com/MarcoFalke/rapidcheck/archive
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=9640926223c00af45bce4c7df8b756b5458a89b2ba74cfe3e404467f13ce26df
|
||||
|
||||
define $(package)_config_cmds
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=true .
|
||||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE) && \
|
||||
mkdir -p $($(package)_staging_dir)$(host_prefix)/include && \
|
||||
cp -a include/* $($(package)_staging_dir)$(host_prefix)/include/ && \
|
||||
cp -a extras/boost_test/include/rapidcheck/* $($(package)_staging_dir)$(host_prefix)/include/rapidcheck/ && \
|
||||
mkdir -p $($(package)_staging_dir)$(host_prefix)/lib && \
|
||||
cp -a librapidcheck.a $($(package)_staging_dir)$(host_prefix)/lib/
|
||||
endef
|
||||
|
|
@ -75,6 +75,7 @@ The Bitcoin repo's [root README](/README.md) contains relevant information on th
|
|||
- [Tor Support](tor.md)
|
||||
- [Init Scripts (systemd/upstart/openrc)](init.md)
|
||||
- [ZMQ](zmq.md)
|
||||
- [PSBT support](psbt.md)
|
||||
|
||||
License
|
||||
---------------------
|
||||
|
|
|
|||
|
|
@ -64,6 +64,17 @@ Build Bitcoin Core
|
|||
|
||||
make deploy
|
||||
|
||||
Disable-wallet mode
|
||||
--------------------
|
||||
When the intention is to run only a P2P node without a wallet, Bitcoin Core may be compiled in
|
||||
disable-wallet mode with:
|
||||
|
||||
./configure --disable-wallet
|
||||
|
||||
In this case there is no dependency on Berkeley DB 4.8.
|
||||
|
||||
Mining is also possible in disable-wallet mode using the `getblocktemplate` RPC call.
|
||||
|
||||
Running
|
||||
-------
|
||||
|
||||
|
|
|
|||
|
|
@ -234,8 +234,7 @@ disable-wallet mode with:
|
|||
|
||||
In this case there is no dependency on Berkeley DB 4.8.
|
||||
|
||||
Mining is also possible in disable-wallet mode, but only using the `getblocktemplate` RPC
|
||||
call not `getwork`.
|
||||
Mining is also possible in disable-wallet mode using the `getblocktemplate` RPC call.
|
||||
|
||||
Additional Configure Flags
|
||||
--------------------------
|
||||
|
|
@ -284,4 +283,3 @@ To build executables for ARM:
|
|||
|
||||
|
||||
For further documentation on the depends system see [README.md](../depends/README.md) in the depends directory.
|
||||
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ Strings and formatting
|
|||
- *Rationale*: These functions do overflow checking, and avoid pesky locale issues.
|
||||
|
||||
- Avoid using locale dependent functions if possible. You can use the provided
|
||||
[`lint-locale-dependence.sh`](/contrib/devtools/lint-locale-dependence.sh)
|
||||
[`lint-locale-dependence.sh`](/test/lint/lint-locale-dependence.sh)
|
||||
to check for accidental use of locale dependent functions.
|
||||
|
||||
- *Rationale*: Unnecessary locale dependence can cause bugs that are very tricky to isolate and fix.
|
||||
|
|
|
|||
132
doc/psbt.md
Normal file
132
doc/psbt.md
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# PSBT Howto for Bitcoin Core
|
||||
|
||||
Since Bitcoin Core 0.17, an RPC interface exists for Partially Signed Bitcoin
|
||||
Transactions (PSBTs, as specified in
|
||||
[BIP 174](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki)).
|
||||
|
||||
This document describes the overall workflow for producing signed transactions
|
||||
through the use of PSBT, and the specific RPC commands used in typical
|
||||
scenarios.
|
||||
|
||||
## PSBT in general
|
||||
|
||||
PSBT is an interchange format for Bitcoin transactions that are not fully signed
|
||||
yet, together with relevant metadata to help entities work towards signing it.
|
||||
It is intended to simplify workflows where multiple parties need to cooperate to
|
||||
produce a transaction. Examples include hardware wallets, multisig setups, and
|
||||
[CoinJoin](https://bitcointalk.org/?topic=279249) transactions.
|
||||
|
||||
### Overall workflow
|
||||
|
||||
Overall, the construction of a fully signed Bitcoin transaction goes through the
|
||||
following steps:
|
||||
|
||||
- A **Creator** proposes a particular transaction to be created. They construct
|
||||
a PSBT that contains certain inputs and outputs, but no additional metadata.
|
||||
- For each input, an **Updater** adds information about the UTXOs being spent by
|
||||
the transaction to the PSBT. They also add information about the scripts and
|
||||
public keys involved in each of the inputs (and possibly outputs) of the PSBT.
|
||||
- **Signers** inspect the transaction and its metadata to decide whether they
|
||||
agree with the transaction. They can use amount information from the UTXOs
|
||||
to assess the values and fees involved. If they agree, they produce a
|
||||
partial signature for the inputs for which they have relevant key(s).
|
||||
- A **Finalizer** is run for each input to convert the partial signatures and
|
||||
possibly script information into a final `scriptSig` and/or `scriptWitness`.
|
||||
- An **Extractor** produces a valid Bitcoin transaction (in network format)
|
||||
from a PSBT for which all inputs are finalized.
|
||||
|
||||
Generally, each of the above (excluding Creator and Extractor) will simply
|
||||
add more and more data to a particular PSBT, until all inputs are fully signed.
|
||||
In a naive workflow, they all have to operate sequentially, passing the PSBT
|
||||
from one to the next, until the Extractor can convert it to a real transaction.
|
||||
In order to permit parallel operation, **Combiners** can be employed which merge
|
||||
metadata from different PSBTs for the same unsigned transaction.
|
||||
|
||||
The names above in bold are the names of the roles defined in BIP174. They're
|
||||
useful in understanding the underlying steps, but in practice, software and
|
||||
hardware implementations will typically implement multiple roles simultaneously.
|
||||
|
||||
## PSBT in Bitcoin Core
|
||||
|
||||
### RPCs
|
||||
|
||||
- **`converttopsbt` (Creator)** is a utility RPC that converts an
|
||||
unsigned raw transaction to PSBT format. It ignores existing signatures.
|
||||
- **`createpsbt` (Creator)** is a utility RPC that takes a list of inputs and
|
||||
outputs and converts them to a PSBT with no additional information. It is
|
||||
equivalent to calling `createrawtransaction` followed by `converttopsbt`.
|
||||
- **`walletcreatefundedpsbt` (Creator, Updater)** is a wallet RPC that creates a
|
||||
PSBT with the specified inputs and outputs, adds additional inputs and change
|
||||
to it to balance it out, and adds relevant metadata. In particular, for inputs
|
||||
that the wallet knows about (counting towards its normal or watch-only
|
||||
balance), UTXO information will be added. For outputs and inputs with UTXO
|
||||
information present, key and script information will be added which the wallet
|
||||
knows about. It is equivalent to running `createrawtransaction`, followed by
|
||||
`fundrawtransaction`, and `converttopsbt`.
|
||||
- **`walletprocesspsbt` (Updater, Signer, Finalizer)** is a wallet RPC that takes as
|
||||
input a PSBT, adds UTXO, key, and script data to inputs and outputs that miss
|
||||
it, and optionally signs inputs. Where possible it also finalizes the partial
|
||||
signatures.
|
||||
- **`finalizepsbt` (Finalizer, Extractor)** is a utility RPC that finalizes any
|
||||
partial signatures, and if all inputs are finalized, converts the result to a
|
||||
fully signed transaction which can be broadcast with `sendrawtransaction`.
|
||||
- **`combinepsbt` (Combiner)** is a utility RPC that implements a Combiner. It
|
||||
can be used at any point in the workflow to merge information added to
|
||||
different versions of the same PSBT. In particular it is useful to combine the
|
||||
output of multiple Updaters or Signers.
|
||||
- **`decodepsbt`** is a diagnostic utility RPC which will show all information in
|
||||
a PSBT in human-readable form, as well as compute its eventual fee if known.
|
||||
|
||||
### Workflows
|
||||
|
||||
#### Multisig with multiple Bitcoin Core instances
|
||||
|
||||
Alice, Bob, and Carol want to create a 2-of-3 multisig address. They're all using
|
||||
Bitcoin Core. We assume their wallets only contain the multisig funds. In case
|
||||
they also have a personal wallet, this can be accomplished through the
|
||||
multiwallet feature - possibly resulting in a need to add `-rpcwallet=name` to
|
||||
the command line in case `bitcoin-cli` is used.
|
||||
|
||||
Setup:
|
||||
- All three call `getnewaddress` to create a new address; call these addresses
|
||||
*Aalice*, *Abob*, and *Acarol*.
|
||||
- All three call `getaddressinfo X`, with *X* their respective address, and
|
||||
remember the corresponding public keys. Call these public keys *Kalice*,
|
||||
*Kbob*, and *Kcarol*.
|
||||
- All three now run `addmultisigaddress 2 ["Kalice","Kbob","Kcarol"]` to teach
|
||||
their wallet about the multisig script. Call the address produced by this
|
||||
command *Amulti*. They may be required to explicitly specify the same
|
||||
addresstype option each, to avoid constructing different versions due to
|
||||
differences in configuration.
|
||||
- They also run `importaddress "Amulti" "" false` to make their wallets treat
|
||||
payments to *Amulti* as contributing to the watch-only balance.
|
||||
- Others can verify the produced address by running
|
||||
`createmultisig 2 ["Kalice","Kbob","Kcarol"]`, and expecting *Amulti* as
|
||||
output. Again, it may be necessary to explicitly specify the addresstype
|
||||
in order to get a result that matches. This command won't enable them to
|
||||
initiate transactions later, however.
|
||||
- They can now give out *D* as address others can pay to.
|
||||
|
||||
Later, when *V* BTC has been received on *Amulti*, and Bob and Carol want to
|
||||
move the coins in their entirety to address *Asend*, with no change. Alice
|
||||
does not need to be involved.
|
||||
- One of them - let's assume Carol here - initiates the creation. She runs
|
||||
`walletcreatefundedpsbt [] {"Asend":V} 0 false {"subtractFeeFromOutputs":[0], "includeWatching":true}`.
|
||||
We call the resulting PSBT *P*. P does not contain any signatures.
|
||||
- Carol needs to sign the transaction herself. In order to do so, she runs
|
||||
`walletprocesspsbt P`, and gives the resulting PSBT *P2* to Bob.
|
||||
- Bob inspects the PSBT using `decodepsbt "P2"` to determine if the transaction
|
||||
has indeed just the expected input, and an output to *Asend*, and the fee is
|
||||
reasonable. If he agrees, he calls `walletprocesspsbt "P2"` to sign. The
|
||||
resulting PSBT *P3* contains both Carol's and Bob's signature.
|
||||
- Now anyone can call `finalizepsbt "P2"` to extract a fully signed transaction
|
||||
*T*.
|
||||
- Finally anyone can broadcast the transaction using `sendrawtransaction "T"`.
|
||||
|
||||
In case there are more signers, it may be advantageous to let them all sign in
|
||||
parallel, rather passing the PSBT from one signer to the next one. In the
|
||||
above example this would translate to Carol handing a copy of *P* to each signer
|
||||
separately. They can then all invoke `walletprocesspsbt P`, and end up with
|
||||
their individually-signed PSBT structures. They then all send those back to
|
||||
Carol (or anyone) who can combine them using `combinepsbt`. The last two steps
|
||||
(`finalizepsbt` and `sendrawtransaction`) remain unchanged.
|
||||
8
doc/release-notes-14023.md
Normal file
8
doc/release-notes-14023.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
Account API removed
|
||||
-------------------
|
||||
|
||||
The 'account' API was deprecated in v0.17 and has been fully removed in v0.18.
|
||||
The 'label' API was introduced in v0.17 as a replacement for accounts.
|
||||
|
||||
See the release notes from v0.17 for a full description of the changes from the
|
||||
'account' API to the 'label' API.
|
||||
|
|
@ -59,6 +59,16 @@ support versions of macOS older than 10.10.
|
|||
Notable changes
|
||||
===============
|
||||
|
||||
Command line option changes
|
||||
---------------------------
|
||||
|
||||
The `-enablebip61` command line option (introduced in Bitcoin Core 0.17.0) is
|
||||
used to toggle sending of BIP 61 reject messages. Reject messages have no use
|
||||
case on the P2P network and are only logged for debugging by most network
|
||||
nodes. The option will now by default be off for improved privacy and security
|
||||
as well as reduced upload usage. The option can explicitly be turned on for
|
||||
local-network debugging purposes.
|
||||
|
||||
Example item
|
||||
------------
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ API, to create and destroy 'ephemeral' hidden services programmatically.
|
|||
Bitcoin Core has been updated to make use of this.
|
||||
|
||||
This means that if Tor is running (and proper authentication has been configured),
|
||||
Bitcoin Core automatically creates a hidden service to listen on. This will positively
|
||||
Bitcoin Core automatically creates a hidden service to listen on. This will positively
|
||||
affect the number of available .onion nodes.
|
||||
|
||||
This new feature is enabled by default if Bitcoin Core is listening (`-listen`), and
|
||||
|
|
@ -102,8 +102,9 @@ and, if not disabled, configured using the `-torcontrol` and `-torpassword` sett
|
|||
To show verbose debugging information, pass `-debug=tor`.
|
||||
|
||||
Connecting to Tor's control socket API requires one of two authentication methods to be
|
||||
configured. For cookie authentication the user running bitcoind must have write access
|
||||
to the `CookieAuthFile` specified in Tor configuration. In some cases, this is
|
||||
configured. It also requires the control socket to be enabled, e.g. put `ControlPort 9051`
|
||||
in `torrc` config file. For cookie authentication the user running bitcoind must have read
|
||||
access to the `CookieAuthFile` specified in Tor configuration. In some cases this is
|
||||
preconfigured and the creation of a hidden service is automatic. If permission problems
|
||||
are seen with `-debug=tor` they can be resolved by adding both the user running Tor and
|
||||
the user running bitcoind to the same group and setting permissions appropriately. On
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ BITCOIN_CORE_H = \
|
|||
bech32.h \
|
||||
bloom.h \
|
||||
blockencodings.h \
|
||||
blockfilter.h \
|
||||
block_proof.h \
|
||||
chain.h \
|
||||
chainparams.h \
|
||||
|
|
@ -224,6 +225,7 @@ libbitcoin_server_a_SOURCES = \
|
|||
addrman.cpp \
|
||||
bloom.cpp \
|
||||
blockencodings.cpp \
|
||||
blockfilter.cpp \
|
||||
block_proof.cpp \
|
||||
chain.cpp \
|
||||
checkpoints.cpp \
|
||||
|
|
@ -232,6 +234,8 @@ libbitcoin_server_a_SOURCES = \
|
|||
httpserver.cpp \
|
||||
index/base.cpp \
|
||||
index/txindex.cpp \
|
||||
interfaces/handler.cpp \
|
||||
interfaces/node.cpp \
|
||||
init.cpp \
|
||||
dbwrapper.cpp \
|
||||
mainchainrpc.cpp \
|
||||
|
|
@ -266,6 +270,10 @@ libbitcoin_server_a_SOURCES = \
|
|||
versionbits.cpp \
|
||||
$(BITCOIN_CORE_H)
|
||||
|
||||
if !ENABLE_WALLET
|
||||
libbitcoin_server_a_SOURCES += dummywallet.cpp
|
||||
endif
|
||||
|
||||
if ENABLE_ZMQ
|
||||
libbitcoin_zmq_a_CPPFLAGS = $(BITCOIN_INCLUDES) $(ZMQ_CFLAGS)
|
||||
libbitcoin_zmq_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
|
|
@ -427,8 +435,6 @@ libbitcoin_util_a_SOURCES = \
|
|||
compat/glibcxx_sanity.cpp \
|
||||
compat/strnlen.cpp \
|
||||
fs.cpp \
|
||||
interfaces/handler.cpp \
|
||||
interfaces/node.cpp \
|
||||
logging.cpp \
|
||||
random.cpp \
|
||||
rpc/protocol.cpp \
|
||||
|
|
@ -480,7 +486,7 @@ bitcoind_LDADD = \
|
|||
$(LIBMEMENV) \
|
||||
$(LIBSECP256K1)
|
||||
|
||||
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
|
||||
bitcoind_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS)
|
||||
|
||||
# bitcoin-cli binary #
|
||||
bitcoin_cli_SOURCES = bitcoin-cli.cpp
|
||||
|
|
@ -498,7 +504,7 @@ bitcoin_cli_LDADD = \
|
|||
$(LIBBITCOIN_UTIL) \
|
||||
$(LIBBITCOIN_CRYPTO)
|
||||
|
||||
bitcoin_cli_LDADD += $(BOOST_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
|
||||
bitcoin_cli_LDADD += $(BOOST_LIBS) $(CRYPTO_LIBS) $(EVENT_LIBS)
|
||||
#
|
||||
|
||||
# bitcoin-tx binary #
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ bench_bench_bitcoin_SOURCES = \
|
|||
bench/rollingbloom.cpp \
|
||||
bench/crypto_hash.cpp \
|
||||
bench/ccoins_caching.cpp \
|
||||
bench/gcs_filter.cpp \
|
||||
bench/merkle_root.cpp \
|
||||
bench/mempool_eviction.cpp \
|
||||
bench/verify_script.cpp \
|
||||
|
|
@ -55,7 +56,7 @@ if ENABLE_WALLET
|
|||
bench_bench_bitcoin_SOURCES += bench/coin_selection.cpp
|
||||
endif
|
||||
|
||||
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
|
||||
bench_bench_bitcoin_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(EVENT_LIBS)
|
||||
bench_bench_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
|
||||
|
||||
CLEAN_BITCOIN_BENCH = bench/*.gcda bench/*.gcno $(GENERATED_BENCH_FILES)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ TEST_SRCDIR = test
|
|||
TEST_BINARY=test/test_bitcoin$(EXEEXT)
|
||||
|
||||
JSON_TEST_FILES = \
|
||||
test/data/script_tests.json \
|
||||
test/data/base58_encode_decode.json \
|
||||
test/data/blockfilters.json \
|
||||
test/data/key_io_valid.json \
|
||||
test/data/key_io_invalid.json \
|
||||
test/data/script_tests.json \
|
||||
|
|
@ -27,6 +29,7 @@ BITCOIN_TEST_SUITE = \
|
|||
|
||||
# test_bitcoin binary #
|
||||
BITCOIN_TESTS =\
|
||||
test/pegin_witness_tests.cpp \
|
||||
test/arith_uint256_tests.cpp \
|
||||
test/scriptnum10.h \
|
||||
test/addrman_tests.cpp \
|
||||
|
|
@ -39,6 +42,7 @@ BITCOIN_TESTS =\
|
|||
test/bip32_tests.cpp \
|
||||
test/blockchain_tests.cpp \
|
||||
test/blockencodings_tests.cpp \
|
||||
test/blockfilter_tests.cpp \
|
||||
test/bloom_tests.cpp \
|
||||
test/bswap_tests.cpp \
|
||||
test/checkqueue_tests.cpp \
|
||||
|
|
@ -81,6 +85,7 @@ BITCOIN_TESTS =\
|
|||
test/sigopcount_tests.cpp \
|
||||
test/skiplist_tests.cpp \
|
||||
test/streams_tests.cpp \
|
||||
test/sync_tests.cpp \
|
||||
test/timedata_tests.cpp \
|
||||
test/torcontrol_tests.cpp \
|
||||
test/transaction_tests.cpp \
|
||||
|
|
@ -91,13 +96,20 @@ BITCOIN_TESTS =\
|
|||
test/util_tests.cpp \
|
||||
test/validation_block_tests.cpp \
|
||||
test/versionbits_tests.cpp \
|
||||
test/pegin_spent_tests.cpp \
|
||||
test/pegin_witness_tests.cpp
|
||||
test/pegin_spent_tests.cpp
|
||||
# ELEMENTS IN THE END
|
||||
|
||||
if ENABLE_PROPERTY_TESTS
|
||||
BITCOIN_TESTS += \
|
||||
test/key_properties.cpp
|
||||
|
||||
BITCOIN_TEST_SUITE += \
|
||||
test/gen/crypto_gen.cpp \
|
||||
test/gen/crypto_gen.h
|
||||
endif
|
||||
|
||||
if ENABLE_WALLET
|
||||
BITCOIN_TESTS += \
|
||||
wallet/test/accounting_tests.cpp \
|
||||
wallet/test/psbt_wallet_tests.cpp \
|
||||
wallet/test/wallet_tests.cpp \
|
||||
wallet/test/wallet_crypto_tests.cpp \
|
||||
|
|
@ -119,7 +131,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
|
|||
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
|
||||
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS)
|
||||
test_test_bitcoin_LDADD += $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(RAPIDCHECK_LIBS)
|
||||
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
|
||||
|
||||
if ENABLE_ZMQ
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ uint32_t PolyMod(const data& v)
|
|||
// v, it corresponds to x^2 + v0*x + v1 mod g(x). As 1 mod g(x) = 1, that is the starting value
|
||||
// for `c`.
|
||||
uint32_t c = 1;
|
||||
for (auto v_i : v) {
|
||||
for (const auto v_i : v) {
|
||||
// We want to update `c` to correspond to a polynomial with one extra term. If the initial
|
||||
// value of `c` consists of the coefficients of c(x) = f(x) mod g(x), we modify it to
|
||||
// correspond to c'(x) = (f(x) * x + v_i) mod g(x), where v_i is the next input to
|
||||
|
|
@ -149,7 +149,7 @@ std::string Encode(const std::string& hrp, const data& values) {
|
|||
data combined = Cat(values, checksum);
|
||||
std::string ret = hrp + '1';
|
||||
ret.reserve(ret.size() + combined.size());
|
||||
for (auto c : combined) {
|
||||
for (const auto c : combined) {
|
||||
ret += CHARSET[c];
|
||||
}
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
|
||||
|
||||
static const int64_t DEFAULT_BENCH_EVALUATIONS = 5;
|
||||
static const char* DEFAULT_BENCH_FILTER = ".*";
|
||||
static const char* DEFAULT_BENCH_SCALING = "1.0";
|
||||
|
|
|
|||
|
|
@ -80,18 +80,16 @@ static void SipHash_32b(benchmark::State& state)
|
|||
static void FastRandom_32bit(benchmark::State& state)
|
||||
{
|
||||
FastRandomContext rng(true);
|
||||
uint32_t x = 0;
|
||||
while (state.KeepRunning()) {
|
||||
x += rng.rand32();
|
||||
rng.rand32();
|
||||
}
|
||||
}
|
||||
|
||||
static void FastRandom_1bit(benchmark::State& state)
|
||||
{
|
||||
FastRandomContext rng(true);
|
||||
uint32_t x = 0;
|
||||
while (state.KeepRunning()) {
|
||||
x += rng.randbool();
|
||||
rng.randbool();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
43
src/bench/gcs_filter.cpp
Normal file
43
src/bench/gcs_filter.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <bench/bench.h>
|
||||
#include <blockfilter.h>
|
||||
|
||||
static void ConstructGCSFilter(benchmark::State& state)
|
||||
{
|
||||
GCSFilter::ElementSet elements;
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
GCSFilter::Element element(32);
|
||||
element[0] = static_cast<unsigned char>(i);
|
||||
element[1] = static_cast<unsigned char>(i >> 8);
|
||||
elements.insert(std::move(element));
|
||||
}
|
||||
|
||||
uint64_t siphash_k0 = 0;
|
||||
while (state.KeepRunning()) {
|
||||
GCSFilter filter(siphash_k0, 0, 20, 1 << 20, elements);
|
||||
|
||||
siphash_k0++;
|
||||
}
|
||||
}
|
||||
|
||||
static void MatchGCSFilter(benchmark::State& state)
|
||||
{
|
||||
GCSFilter::ElementSet elements;
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
GCSFilter::Element element(32);
|
||||
element[0] = static_cast<unsigned char>(i);
|
||||
element[1] = static_cast<unsigned char>(i >> 8);
|
||||
elements.insert(std::move(element));
|
||||
}
|
||||
GCSFilter filter(0, 0, 20, 1 << 20, elements);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
filter.Match(GCSFilter::Element());
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(ConstructGCSFilter, 1000);
|
||||
BENCHMARK(MatchGCSFilter, 50 * 1000);
|
||||
|
|
@ -17,10 +17,9 @@ static void AddTx(const CTransactionRef& tx, const CAmount& nFee, CTxMemPool& po
|
|||
unsigned int sigOpCost = 4;
|
||||
LockPoints lp;
|
||||
std::set<std::pair<uint256, COutPoint>> setPeginsSpent;
|
||||
pool.addUnchecked(tx->GetHash(), CTxMemPoolEntry(
|
||||
pool.addUnchecked(CTxMemPoolEntry(
|
||||
tx, nFee, nTime, nHeight,
|
||||
spendsCoinbase, sigOpCost, lp,
|
||||
setPeginsSpent));
|
||||
spendsCoinbase, sigOpCost, lp, setPeginsSpent));
|
||||
}
|
||||
|
||||
// Right now this is only testing eviction performance in an extremely small
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ static void RollingBloom(benchmark::State& state)
|
|||
CRollingBloomFilter filter(120000, 0.000001);
|
||||
std::vector<unsigned char> data(32);
|
||||
uint32_t count = 0;
|
||||
uint64_t match = 0;
|
||||
while (state.KeepRunning()) {
|
||||
count++;
|
||||
data[0] = count;
|
||||
|
|
@ -25,7 +24,7 @@ static void RollingBloom(benchmark::State& state)
|
|||
data[1] = count >> 16;
|
||||
data[2] = count >> 8;
|
||||
data[3] = count;
|
||||
match += filter.contains(data);
|
||||
filter.contains(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <univalue.h>
|
||||
|
||||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
|
||||
|
||||
static const char DEFAULT_RPCCONNECT[] = "127.0.0.1";
|
||||
static const int DEFAULT_HTTP_CLIENT_TIMEOUT=900;
|
||||
static const bool DEFAULT_NAMED=false;
|
||||
|
|
@ -33,6 +35,7 @@ static void SetupCliArgs()
|
|||
{
|
||||
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
|
||||
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
|
||||
const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
|
||||
|
||||
gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-version", "Print version and exit", false, OptionsCategory::OPTIONS);
|
||||
|
|
@ -43,9 +46,9 @@ static void SetupCliArgs()
|
|||
gArgs.AddArg("-named", strprintf("Pass named instead of positional arguments (default: %s)", DEFAULT_NAMED), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcclienttimeout=<n>", strprintf("Timeout in seconds during HTTP requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcconnect=<ip>", strprintf("Send commands to node running on <ip> (default: %s)", DEFAULT_RPCCONNECT), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpccookiefile=<loc>", _("Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)"), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcport=<port>", strprintf("Connect to JSON-RPC on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcwait", "Wait for RPC server to start", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-rpcwallet=<walletname>", "Send RPC for non-default wallet on RPC server (needs to exactly match corresponding -wallet option passed to bitcoind)", false, OptionsCategory::OPTIONS);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ static bool fCreateBlank;
|
|||
static std::map<std::string,UniValue> registers;
|
||||
static const int CONTINUE_EXECUTION=-1;
|
||||
|
||||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
|
||||
|
||||
static void SetupBitcoinTxArgs()
|
||||
{
|
||||
gArgs.AddArg("-?", "This help message", false, OptionsCategory::OPTIONS);
|
||||
|
|
@ -383,7 +385,7 @@ static void MutateTxAddOutMultiSig(CMutableTransaction& tx, const std::string& s
|
|||
CScript scriptPubKey = GetScriptForMultisig(required, pubkeys);
|
||||
|
||||
if (bSegWit) {
|
||||
for (CPubKey& pubkey : pubkeys) {
|
||||
for (const CPubKey& pubkey : pubkeys) {
|
||||
if (!pubkey.IsCompressed()) {
|
||||
throw std::runtime_error("Uncompressed pubkeys are not useable for SegWit outputs");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
|
||||
|
||||
/* Introduction text for doxygen: */
|
||||
|
||||
/*! \mainpage Developer documentation
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ ReadStatus PartiallyDownloadedBlock::InitData(const CBlockHeaderAndShortTxIDs& c
|
|||
break;
|
||||
}
|
||||
|
||||
LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, SER_NETWORK, PROTOCOL_VERSION));
|
||||
LogPrint(BCLog::CMPCTBLOCK, "Initialized PartiallyDownloadedBlock for block %s using a cmpctblock of size %lu\n", cmpctblock.header.GetHash().ToString(), GetSerializeSize(cmpctblock, PROTOCOL_VERSION));
|
||||
|
||||
return READ_STATUS_OK;
|
||||
}
|
||||
|
|
|
|||
261
src/blockfilter.cpp
Normal file
261
src/blockfilter.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright (c) 2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <blockfilter.h>
|
||||
#include <hash.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/script.h>
|
||||
#include <streams.h>
|
||||
|
||||
/// SerType used to serialize parameters in GCS filter encoding.
|
||||
static constexpr int GCS_SER_TYPE = SER_NETWORK;
|
||||
|
||||
/// Protocol version used to serialize parameters in GCS filter encoding.
|
||||
static constexpr int GCS_SER_VERSION = 0;
|
||||
|
||||
template <typename OStream>
|
||||
static void GolombRiceEncode(BitStreamWriter<OStream>& bitwriter, uint8_t P, uint64_t x)
|
||||
{
|
||||
// Write quotient as unary-encoded: q 1's followed by one 0.
|
||||
uint64_t q = x >> P;
|
||||
while (q > 0) {
|
||||
int nbits = q <= 64 ? static_cast<int>(q) : 64;
|
||||
bitwriter.Write(~0ULL, nbits);
|
||||
q -= nbits;
|
||||
}
|
||||
bitwriter.Write(0, 1);
|
||||
|
||||
// Write the remainder in P bits. Since the remainder is just the bottom
|
||||
// P bits of x, there is no need to mask first.
|
||||
bitwriter.Write(x, P);
|
||||
}
|
||||
|
||||
template <typename IStream>
|
||||
static uint64_t GolombRiceDecode(BitStreamReader<IStream>& bitreader, uint8_t P)
|
||||
{
|
||||
// Read unary-encoded quotient: q 1's followed by one 0.
|
||||
uint64_t q = 0;
|
||||
while (bitreader.Read(1) == 1) {
|
||||
++q;
|
||||
}
|
||||
|
||||
uint64_t r = bitreader.Read(P);
|
||||
|
||||
return (q << P) + r;
|
||||
}
|
||||
|
||||
// Map a value x that is uniformly distributed in the range [0, 2^64) to a
|
||||
// value uniformly distributed in [0, n) by returning the upper 64 bits of
|
||||
// x * n.
|
||||
//
|
||||
// See: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
|
||||
static uint64_t MapIntoRange(uint64_t x, uint64_t n)
|
||||
{
|
||||
#ifdef __SIZEOF_INT128__
|
||||
return (static_cast<unsigned __int128>(x) * static_cast<unsigned __int128>(n)) >> 64;
|
||||
#else
|
||||
// To perform the calculation on 64-bit numbers without losing the
|
||||
// result to overflow, split the numbers into the most significant and
|
||||
// least significant 32 bits and perform multiplication piece-wise.
|
||||
//
|
||||
// See: https://stackoverflow.com/a/26855440
|
||||
uint64_t x_hi = x >> 32;
|
||||
uint64_t x_lo = x & 0xFFFFFFFF;
|
||||
uint64_t n_hi = n >> 32;
|
||||
uint64_t n_lo = n & 0xFFFFFFFF;
|
||||
|
||||
uint64_t ac = x_hi * n_hi;
|
||||
uint64_t ad = x_hi * n_lo;
|
||||
uint64_t bc = x_lo * n_hi;
|
||||
uint64_t bd = x_lo * n_lo;
|
||||
|
||||
uint64_t mid34 = (bd >> 32) + (bc & 0xFFFFFFFF) + (ad & 0xFFFFFFFF);
|
||||
uint64_t upper64 = ac + (bc >> 32) + (ad >> 32) + (mid34 >> 32);
|
||||
return upper64;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t GCSFilter::HashToRange(const Element& element) const
|
||||
{
|
||||
uint64_t hash = CSipHasher(m_siphash_k0, m_siphash_k1)
|
||||
.Write(element.data(), element.size())
|
||||
.Finalize();
|
||||
return MapIntoRange(hash, m_F);
|
||||
}
|
||||
|
||||
std::vector<uint64_t> GCSFilter::BuildHashedSet(const ElementSet& elements) const
|
||||
{
|
||||
std::vector<uint64_t> hashed_elements;
|
||||
hashed_elements.reserve(elements.size());
|
||||
for (const Element& element : elements) {
|
||||
hashed_elements.push_back(HashToRange(element));
|
||||
}
|
||||
std::sort(hashed_elements.begin(), hashed_elements.end());
|
||||
return hashed_elements;
|
||||
}
|
||||
|
||||
GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M)
|
||||
: m_siphash_k0(siphash_k0), m_siphash_k1(siphash_k1), m_P(P), m_M(M), m_N(0), m_F(0)
|
||||
{}
|
||||
|
||||
GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
|
||||
std::vector<unsigned char> encoded_filter)
|
||||
: GCSFilter(siphash_k0, siphash_k1, P, M)
|
||||
{
|
||||
m_encoded = std::move(encoded_filter);
|
||||
|
||||
VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);
|
||||
|
||||
uint64_t N = ReadCompactSize(stream);
|
||||
m_N = static_cast<uint32_t>(N);
|
||||
if (m_N != N) {
|
||||
throw std::ios_base::failure("N must be <2^32");
|
||||
}
|
||||
m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_M);
|
||||
|
||||
// Verify that the encoded filter contains exactly N elements. If it has too much or too little
|
||||
// data, a std::ios_base::failure exception will be raised.
|
||||
BitStreamReader<VectorReader> bitreader(stream);
|
||||
for (uint64_t i = 0; i < m_N; ++i) {
|
||||
GolombRiceDecode(bitreader, m_P);
|
||||
}
|
||||
if (!stream.empty()) {
|
||||
throw std::ios_base::failure("encoded_filter contains excess data");
|
||||
}
|
||||
}
|
||||
|
||||
GCSFilter::GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
|
||||
const ElementSet& elements)
|
||||
: GCSFilter(siphash_k0, siphash_k1, P, M)
|
||||
{
|
||||
size_t N = elements.size();
|
||||
m_N = static_cast<uint32_t>(N);
|
||||
if (m_N != N) {
|
||||
throw std::invalid_argument("N must be <2^32");
|
||||
}
|
||||
m_F = static_cast<uint64_t>(m_N) * static_cast<uint64_t>(m_M);
|
||||
|
||||
CVectorWriter stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);
|
||||
|
||||
WriteCompactSize(stream, m_N);
|
||||
|
||||
if (elements.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BitStreamWriter<CVectorWriter> bitwriter(stream);
|
||||
|
||||
uint64_t last_value = 0;
|
||||
for (uint64_t value : BuildHashedSet(elements)) {
|
||||
uint64_t delta = value - last_value;
|
||||
GolombRiceEncode(bitwriter, m_P, delta);
|
||||
last_value = value;
|
||||
}
|
||||
|
||||
bitwriter.Flush();
|
||||
}
|
||||
|
||||
bool GCSFilter::MatchInternal(const uint64_t* element_hashes, size_t size) const
|
||||
{
|
||||
VectorReader stream(GCS_SER_TYPE, GCS_SER_VERSION, m_encoded, 0);
|
||||
|
||||
// Seek forward by size of N
|
||||
uint64_t N = ReadCompactSize(stream);
|
||||
assert(N == m_N);
|
||||
|
||||
BitStreamReader<VectorReader> bitreader(stream);
|
||||
|
||||
uint64_t value = 0;
|
||||
size_t hashes_index = 0;
|
||||
for (uint32_t i = 0; i < m_N; ++i) {
|
||||
uint64_t delta = GolombRiceDecode(bitreader, m_P);
|
||||
value += delta;
|
||||
|
||||
while (true) {
|
||||
if (hashes_index == size) {
|
||||
return false;
|
||||
} else if (element_hashes[hashes_index] == value) {
|
||||
return true;
|
||||
} else if (element_hashes[hashes_index] > value) {
|
||||
break;
|
||||
}
|
||||
|
||||
hashes_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GCSFilter::Match(const Element& element) const
|
||||
{
|
||||
uint64_t query = HashToRange(element);
|
||||
return MatchInternal(&query, 1);
|
||||
}
|
||||
|
||||
bool GCSFilter::MatchAny(const ElementSet& elements) const
|
||||
{
|
||||
const std::vector<uint64_t> queries = BuildHashedSet(elements);
|
||||
return MatchInternal(queries.data(), queries.size());
|
||||
}
|
||||
|
||||
static GCSFilter::ElementSet BasicFilterElements(const CBlock& block,
|
||||
const CBlockUndo& block_undo)
|
||||
{
|
||||
GCSFilter::ElementSet elements;
|
||||
|
||||
for (const CTransactionRef& tx : block.vtx) {
|
||||
for (const CTxOut& txout : tx->vout) {
|
||||
const CScript& script = txout.scriptPubKey;
|
||||
if (script.empty() || script[0] == OP_RETURN) continue;
|
||||
elements.emplace(script.begin(), script.end());
|
||||
}
|
||||
}
|
||||
|
||||
for (const CTxUndo& tx_undo : block_undo.vtxundo) {
|
||||
for (const Coin& prevout : tx_undo.vprevout) {
|
||||
const CScript& script = prevout.out.scriptPubKey;
|
||||
if (script.empty()) continue;
|
||||
elements.emplace(script.begin(), script.end());
|
||||
}
|
||||
}
|
||||
|
||||
return elements;
|
||||
}
|
||||
|
||||
BlockFilter::BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo)
|
||||
: m_filter_type(filter_type), m_block_hash(block.GetHash())
|
||||
{
|
||||
switch (m_filter_type) {
|
||||
case BlockFilterType::BASIC:
|
||||
m_filter = GCSFilter(m_block_hash.GetUint64(0), m_block_hash.GetUint64(1),
|
||||
BASIC_FILTER_P, BASIC_FILTER_M,
|
||||
BasicFilterElements(block, block_undo));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::invalid_argument("unknown filter_type");
|
||||
}
|
||||
}
|
||||
|
||||
uint256 BlockFilter::GetHash() const
|
||||
{
|
||||
const std::vector<unsigned char>& data = GetEncodedFilter();
|
||||
|
||||
uint256 result;
|
||||
CHash256().Write(data.data(), data.size()).Finalize(result.begin());
|
||||
return result;
|
||||
}
|
||||
|
||||
uint256 BlockFilter::ComputeHeader(const uint256& prev_header) const
|
||||
{
|
||||
const uint256& filter_hash = GetHash();
|
||||
|
||||
uint256 result;
|
||||
CHash256()
|
||||
.Write(filter_hash.begin(), filter_hash.size())
|
||||
.Write(prev_header.begin(), prev_header.size())
|
||||
.Finalize(result.begin());
|
||||
return result;
|
||||
}
|
||||
145
src/blockfilter.h
Normal file
145
src/blockfilter.h
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
// Copyright (c) 2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_BLOCKFILTER_H
|
||||
#define BITCOIN_BLOCKFILTER_H
|
||||
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include <primitives/block.h>
|
||||
#include <serialize.h>
|
||||
#include <uint256.h>
|
||||
#include <undo.h>
|
||||
|
||||
/**
|
||||
* This implements a Golomb-coded set as defined in BIP 158. It is a
|
||||
* compact, probabilistic data structure for testing set membership.
|
||||
*/
|
||||
class GCSFilter
|
||||
{
|
||||
public:
|
||||
typedef std::vector<unsigned char> Element;
|
||||
typedef std::set<Element> ElementSet;
|
||||
|
||||
private:
|
||||
uint64_t m_siphash_k0;
|
||||
uint64_t m_siphash_k1;
|
||||
uint8_t m_P; //!< Golomb-Rice coding parameter
|
||||
uint32_t m_M; //!< Inverse false positive rate
|
||||
uint32_t m_N; //!< Number of elements in the filter
|
||||
uint64_t m_F; //!< Range of element hashes, F = N * M
|
||||
std::vector<unsigned char> m_encoded;
|
||||
|
||||
/** Hash a data element to an integer in the range [0, N * M). */
|
||||
uint64_t HashToRange(const Element& element) const;
|
||||
|
||||
std::vector<uint64_t> BuildHashedSet(const ElementSet& elements) const;
|
||||
|
||||
/** Helper method used to implement Match and MatchAny */
|
||||
bool MatchInternal(const uint64_t* sorted_element_hashes, size_t size) const;
|
||||
|
||||
public:
|
||||
|
||||
/** Constructs an empty filter. */
|
||||
GCSFilter(uint64_t siphash_k0 = 0, uint64_t siphash_k1 = 0, uint8_t P = 0, uint32_t M = 0);
|
||||
|
||||
/** Reconstructs an already-created filter from an encoding. */
|
||||
GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
|
||||
std::vector<unsigned char> encoded_filter);
|
||||
|
||||
/** Builds a new filter from the params and set of elements. */
|
||||
GCSFilter(uint64_t siphash_k0, uint64_t siphash_k1, uint8_t P, uint32_t M,
|
||||
const ElementSet& elements);
|
||||
|
||||
uint8_t GetP() const { return m_P; }
|
||||
uint32_t GetN() const { return m_N; }
|
||||
uint32_t GetM() const { return m_M; }
|
||||
const std::vector<unsigned char>& GetEncoded() const { return m_encoded; }
|
||||
|
||||
/**
|
||||
* Checks if the element may be in the set. False positives are possible
|
||||
* with probability 1/M.
|
||||
*/
|
||||
bool Match(const Element& element) const;
|
||||
|
||||
/**
|
||||
* Checks if any of the given elements may be in the set. False positives
|
||||
* are possible with probability 1/M per element checked. This is more
|
||||
* efficient that checking Match on multiple elements separately.
|
||||
*/
|
||||
bool MatchAny(const ElementSet& elements) const;
|
||||
};
|
||||
|
||||
constexpr uint8_t BASIC_FILTER_P = 19;
|
||||
constexpr uint32_t BASIC_FILTER_M = 784931;
|
||||
|
||||
enum BlockFilterType : uint8_t
|
||||
{
|
||||
BASIC = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* Complete block filter struct as defined in BIP 157. Serialization matches
|
||||
* payload of "cfilter" messages.
|
||||
*/
|
||||
class BlockFilter
|
||||
{
|
||||
private:
|
||||
BlockFilterType m_filter_type;
|
||||
uint256 m_block_hash;
|
||||
GCSFilter m_filter;
|
||||
|
||||
public:
|
||||
|
||||
// Construct a new BlockFilter of the specified type from a block.
|
||||
BlockFilter(BlockFilterType filter_type, const CBlock& block, const CBlockUndo& block_undo);
|
||||
|
||||
BlockFilterType GetFilterType() const { return m_filter_type; }
|
||||
|
||||
const GCSFilter& GetFilter() const { return m_filter; }
|
||||
|
||||
const std::vector<unsigned char>& GetEncodedFilter() const
|
||||
{
|
||||
return m_filter.GetEncoded();
|
||||
}
|
||||
|
||||
// Compute the filter hash.
|
||||
uint256 GetHash() const;
|
||||
|
||||
// Compute the filter header given the previous one.
|
||||
uint256 ComputeHeader(const uint256& prev_header) const;
|
||||
|
||||
template <typename Stream>
|
||||
void Serialize(Stream& s) const {
|
||||
s << m_block_hash
|
||||
<< static_cast<uint8_t>(m_filter_type)
|
||||
<< m_filter.GetEncoded();
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
void Unserialize(Stream& s) {
|
||||
std::vector<unsigned char> encoded_filter;
|
||||
uint8_t filter_type;
|
||||
|
||||
s >> m_block_hash
|
||||
>> filter_type
|
||||
>> encoded_filter;
|
||||
|
||||
m_filter_type = static_cast<BlockFilterType>(filter_type);
|
||||
|
||||
switch (m_filter_type) {
|
||||
case BlockFilterType::BASIC:
|
||||
m_filter = GCSFilter(m_block_hash.GetUint64(0), m_block_hash.GetUint64(1),
|
||||
BASIC_FILTER_P, BASIC_FILTER_M, std::move(encoded_filter));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::ios_base::failure("unknown filter_type");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // BITCOIN_BLOCKFILTER_H
|
||||
|
|
@ -153,11 +153,11 @@ bool CBloomFilter::IsRelevantAndUpdate(const CTransaction& tx)
|
|||
insert(COutPoint(hash, i));
|
||||
else if ((nFlags & BLOOM_UPDATE_MASK) == BLOOM_UPDATE_P2PUBKEY_ONLY)
|
||||
{
|
||||
txnouttype type;
|
||||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
if (Solver(txout.scriptPubKey, type, vSolutions) &&
|
||||
(type == TX_PUBKEY || type == TX_MULTISIG))
|
||||
txnouttype type = Solver(txout.scriptPubKey, vSolutions);
|
||||
if (type == TX_PUBKEY || type == TX_MULTISIG) {
|
||||
insert(COutPoint(hash, i));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <chainparams.h>
|
||||
#include <consensus/merkle.h>
|
||||
|
||||
#include <chainparamsseeds.h>
|
||||
#include <consensus/merkle.h>
|
||||
#include <tinyformat.h>
|
||||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
static CScript StrHexToScriptWithDefault(std::string strScript, const CScript defaultScript)
|
||||
{
|
||||
CScript returnScript;
|
||||
|
|
@ -105,14 +104,6 @@ static void AppendInitialIssuance(CBlock& genesis_block, const COutPoint& prevou
|
|||
/**
|
||||
* Main network
|
||||
*/
|
||||
/**
|
||||
* What makes a good checkpoint block?
|
||||
* + Is surrounded by blocks with reasonable timestamps
|
||||
* (no blocks before with a timestamp after, none after with
|
||||
* timestamp before)
|
||||
* + Contains no strange transactions
|
||||
*/
|
||||
|
||||
class CMainParams : public CChainParams {
|
||||
public:
|
||||
CMainParams() {
|
||||
|
|
@ -155,6 +146,8 @@ public:
|
|||
anyonecanspend_aremine = false;
|
||||
enforce_pak = false;
|
||||
multi_data_permitted = false;
|
||||
consensus.has_parent_chain = false;
|
||||
g_signed_blocks = false;
|
||||
|
||||
/**
|
||||
* The message start string is designed to be unlikely to occur in normal data.
|
||||
|
|
@ -275,6 +268,7 @@ public:
|
|||
anyonecanspend_aremine = false;
|
||||
enforce_pak = false;
|
||||
multi_data_permitted = false;
|
||||
consensus.has_parent_chain = false;
|
||||
|
||||
pchMessageStart[0] = 0x0b;
|
||||
pchMessageStart[1] = 0x11;
|
||||
|
|
@ -370,6 +364,7 @@ public:
|
|||
anyonecanspend_aremine = false;
|
||||
enforce_pak = false;
|
||||
multi_data_permitted = false;
|
||||
consensus.has_parent_chain = false;
|
||||
|
||||
pchMessageStart[0] = 0xfa;
|
||||
pchMessageStart[1] = 0xbf;
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ void CCoinsViewCache::SetPeginSpent(const std::pair<uint256, COutPoint> &outpoin
|
|||
else
|
||||
hadSpent = it->second.peginSpent;
|
||||
|
||||
// If we aren't changing spentness, dont do anything at all
|
||||
// If we aren't changing spentness, don't do anything at all
|
||||
if (hadSpent == fSpent)
|
||||
return;
|
||||
|
||||
|
|
@ -326,7 +326,7 @@ bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
|
|||
return true;
|
||||
}
|
||||
|
||||
static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), SER_NETWORK, PROTOCOL_VERSION);
|
||||
static const size_t MIN_TRANSACTION_OUTPUT_WEIGHT = WITNESS_SCALE_FACTOR * ::GetSerializeSize(CTxOut(), PROTOCOL_VERSION);
|
||||
static const size_t MAX_OUTPUTS_PER_BLOCK = MAX_BLOCK_WEIGHT / MIN_TRANSACTION_OUTPUT_WEIGHT;
|
||||
|
||||
const Coin& AccessByTxid(const CCoinsViewCache& view, const uint256& txid)
|
||||
|
|
|
|||
|
|
@ -303,8 +303,8 @@ public:
|
|||
* Note that lightweight clients may not know anything besides the hash of previous transactions,
|
||||
* so may not be able to calculate this.
|
||||
*
|
||||
* @param[in] tx transaction for which we are checking input total
|
||||
* @return Sum of value of all inputs (scriptSigs)
|
||||
* @param[in] tx transaction for which we are checking input total
|
||||
* @return Sum of value of all inputs (scriptSigs)
|
||||
*/
|
||||
CAmount GetValueIn(const CTransaction& tx) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@
|
|||
|
||||
// GCC 4.8 is missing some C++11 type_traits,
|
||||
// https://www.gnu.org/software/gcc/gcc-5/changes.html
|
||||
#if defined(__GNUC__) && __GNUC__ < 5
|
||||
#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivial
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
|
||||
#define IS_TRIVIALLY_CONSTRUCTIBLE std::has_trivial_default_constructor
|
||||
#else
|
||||
#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivially_constructible
|
||||
#define IS_TRIVIALLY_CONSTRUCTIBLE std::is_trivially_default_constructible
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
|
|||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
if (tx.vin[i].m_is_pegin && !IsValidPeginWitness(tx.vin[i].m_pegin_witness, tx.vin[i].prevout)) {
|
||||
std::string err;
|
||||
if (tx.vin[i].m_is_pegin && !IsValidPeginWitness(tx.vin[i].m_pegin_witness, tx.vin[i].prevout, err, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -184,7 +185,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
|
|||
if (tx.vout.empty())
|
||||
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
|
||||
// Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
|
||||
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
|
||||
if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
|
||||
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
|
||||
|
||||
// Check for negative or overflow output values
|
||||
|
|
@ -239,7 +240,8 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
|
|||
const COutPoint &prevout = tx.vin[i].prevout;
|
||||
if (tx.vin[i].m_is_pegin) {
|
||||
// Check existence and validity of pegin witness
|
||||
if (!IsValidPeginWitness(tx.vin[i].m_pegin_witness, prevout)) {
|
||||
std::string err;
|
||||
if (!IsValidPeginWitness(tx.vin[i].m_pegin_witness, prevout, err, true)) {
|
||||
return state.DoS(0, false, REJECT_PEGIN, "bad-pegin-witness");
|
||||
}
|
||||
std::pair<uint256, COutPoint> pegin = std::make_pair(uint256(tx.vin[i].m_pegin_witness.stack[2]), prevout);
|
||||
|
|
|
|||
|
|
@ -97,16 +97,16 @@ public:
|
|||
// weight = (stripped_size * 3) + total_size.
|
||||
static inline int64_t GetTransactionWeight(const CTransaction& tx)
|
||||
{
|
||||
return ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||
return ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION);
|
||||
}
|
||||
static inline int64_t GetBlockWeight(const CBlock& block)
|
||||
{
|
||||
return ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION);
|
||||
return ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, PROTOCOL_VERSION);
|
||||
}
|
||||
static inline int64_t GetTransactionInputWeight(const CTxIn& txin)
|
||||
{
|
||||
// scriptWitness size is added here because witnesses and txins are split up in segwit serialization.
|
||||
return ::GetSerializeSize(txin, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(txin, SER_NETWORK, PROTOCOL_VERSION) + ::GetSerializeSize(txin.scriptWitness.stack, SER_NETWORK, PROTOCOL_VERSION);
|
||||
return ::GetSerializeSize(txin, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(txin, PROTOCOL_VERSION) + ::GetSerializeSize(txin.scriptWitness.stack, PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
#endif // BITCOIN_CONSENSUS_VALIDATION_H
|
||||
|
|
|
|||
|
|
@ -141,8 +141,7 @@ void ScriptToUniv(const CScript& script, UniValue& out, bool include_address)
|
|||
out.pushKV("hex", HexStr(script.begin(), script.end()));
|
||||
|
||||
std::vector<std::vector<unsigned char>> solns;
|
||||
txnouttype type;
|
||||
Solver(script, type, solns);
|
||||
txnouttype type = Solver(script, solns);
|
||||
out.pushKV("type", GetTxnOutputType(type));
|
||||
|
||||
CTxDestination address;
|
||||
|
|
@ -202,7 +201,7 @@ void TxToUniv(const CTransaction& tx, const uint256& hashBlock, UniValue& entry,
|
|||
entry.pushKV("txid", tx.GetHash().GetHex());
|
||||
entry.pushKV("hash", tx.GetWitnessHash().GetHex());
|
||||
entry.pushKV("version", tx.nVersion);
|
||||
entry.pushKV("size", (int)::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION));
|
||||
entry.pushKV("size", (int)::GetSerializeSize(tx, PROTOCOL_VERSION));
|
||||
entry.pushKV("vsize", (GetTransactionWeight(tx) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR);
|
||||
entry.pushKV("weight", GetTransactionWeight(tx));
|
||||
entry.pushKV("locktime", (int64_t)tx.nLockTime);
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ public:
|
|||
std::array<uint32_t, 8> locs = compute_hashes(e);
|
||||
// Make sure we have not already inserted this element
|
||||
// If we have, make sure that it does not get deleted
|
||||
for (uint32_t loc : locs)
|
||||
for (const uint32_t loc : locs)
|
||||
if (table[loc] == e) {
|
||||
please_keep(loc);
|
||||
epoch_flags[loc] = last_epoch;
|
||||
|
|
@ -405,7 +405,7 @@ public:
|
|||
}
|
||||
for (uint8_t depth = 0; depth < depth_limit; ++depth) {
|
||||
// First try to insert to an empty slot, if one exists
|
||||
for (uint32_t loc : locs) {
|
||||
for (const uint32_t loc : locs) {
|
||||
if (!collection_flags.bit_is_set(loc))
|
||||
continue;
|
||||
table[loc] = std::move(e);
|
||||
|
|
@ -467,7 +467,7 @@ public:
|
|||
inline bool contains(const Element& e, const bool erase) const
|
||||
{
|
||||
std::array<uint32_t, 8> locs = compute_hashes(e);
|
||||
for (uint32_t loc : locs)
|
||||
for (const uint32_t loc : locs)
|
||||
if (table[loc] == e) {
|
||||
if (erase)
|
||||
allow_erase(loc);
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ static void SetMaxOpenFiles(leveldb::Options *options) {
|
|||
// do not interfere with select() loops. On 64-bit Unix hosts this value is
|
||||
// also OK, because up to that amount LevelDB will use an mmap
|
||||
// implementation that does not use extra file descriptors (the fds are
|
||||
// closed after being mmaped).
|
||||
// closed after being mmap'ed).
|
||||
//
|
||||
// Increasing the value beyond the default is dangerous because LevelDB will
|
||||
// fall back to a non-mmap implementation when the file count is too large.
|
||||
|
|
|
|||
51
src/dummywallet.cpp
Normal file
51
src/dummywallet.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2018 The Bitcoin Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <util.h>
|
||||
#include <walletinitinterface.h>
|
||||
|
||||
class CWallet;
|
||||
|
||||
class DummyWalletInit : public WalletInitInterface {
|
||||
public:
|
||||
|
||||
bool HasWalletSupport() const override {return false;}
|
||||
void AddWalletOptions() const override;
|
||||
bool ParameterInteraction() const override {return true;}
|
||||
void RegisterRPC(CRPCTable &) const override {}
|
||||
bool Verify() const override {return true;}
|
||||
bool Open() const override {LogPrintf("No wallet support compiled in!\n"); return true;}
|
||||
void Start(CScheduler& scheduler) const override {}
|
||||
void Flush() const override {}
|
||||
void Stop() const override {}
|
||||
void Close() const override {}
|
||||
};
|
||||
|
||||
void DummyWalletInit::AddWalletOptions() const
|
||||
{
|
||||
std::vector<std::string> opts = {"-addresstype", "-changetype", "-disablewallet", "-discardfee=<amt>", "-fallbackfee=<amt>",
|
||||
"-keypool=<n>", "-mintxfee=<amt>", "-paytxfee=<amt>", "-rescan", "-salvagewallet", "-spendzeroconfchange", "-txconfirmtarget=<n>",
|
||||
"-upgradewallet", "-wallet=<path>", "-walletbroadcast", "-walletdir=<dir>", "-walletnotify=<cmd>", "-walletrbf", "-zapwallettxes=<mode>",
|
||||
"-dblogsize=<n>", "-flushwallet", "-privdb", "-walletrejectlongchains"};
|
||||
gArgs.AddHiddenArgs(opts);
|
||||
}
|
||||
|
||||
const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
|
||||
|
||||
std::vector<std::shared_ptr<CWallet>> GetWallets()
|
||||
{
|
||||
throw std::logic_error("Wallet function called in non-wallet build.");
|
||||
}
|
||||
|
||||
namespace interfaces {
|
||||
|
||||
class Wallet;
|
||||
|
||||
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet)
|
||||
{
|
||||
throw std::logic_error("Wallet function called in non-wallet build.");
|
||||
}
|
||||
|
||||
} // namespace interfaces
|
||||
105
src/fs.cpp
105
src/fs.cpp
|
|
@ -1,15 +1,116 @@
|
|||
#include <fs.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <codecvt>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace fsbridge {
|
||||
|
||||
FILE *fopen(const fs::path& p, const char *mode)
|
||||
{
|
||||
#ifndef WIN32
|
||||
return ::fopen(p.string().c_str(), mode);
|
||||
#else
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
|
||||
return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
FILE *freopen(const fs::path& p, const char *mode, FILE *stream)
|
||||
#ifndef WIN32
|
||||
|
||||
static std::string GetErrorReason() {
|
||||
return std::strerror(errno);
|
||||
}
|
||||
|
||||
FileLock::FileLock(const fs::path& file)
|
||||
{
|
||||
return ::freopen(p.string().c_str(), mode, stream);
|
||||
fd = open(file.string().c_str(), O_RDWR);
|
||||
if (fd == -1) {
|
||||
reason = GetErrorReason();
|
||||
}
|
||||
}
|
||||
|
||||
FileLock::~FileLock()
|
||||
{
|
||||
if (fd != -1) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileLock::TryLock()
|
||||
{
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
struct flock lock;
|
||||
lock.l_type = F_WRLCK;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_start = 0;
|
||||
lock.l_len = 0;
|
||||
if (fcntl(fd, F_SETLK, &lock) == -1) {
|
||||
reason = GetErrorReason();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
static std::string GetErrorReason() {
|
||||
wchar_t* err;
|
||||
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<WCHAR*>(&err), 0, nullptr);
|
||||
std::wstring err_str(err);
|
||||
LocalFree(err);
|
||||
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(err_str);
|
||||
}
|
||||
|
||||
FileLock::FileLock(const fs::path& file)
|
||||
{
|
||||
hFile = CreateFileW(file.wstring().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
reason = GetErrorReason();
|
||||
}
|
||||
}
|
||||
|
||||
FileLock::~FileLock()
|
||||
{
|
||||
if (hFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileLock::TryLock()
|
||||
{
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
_OVERLAPPED overlapped = {0};
|
||||
if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, 0, 0, &overlapped)) {
|
||||
reason = GetErrorReason();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string get_filesystem_error_message(const fs::filesystem_error& e)
|
||||
{
|
||||
#ifndef WIN32
|
||||
return e.what();
|
||||
#else
|
||||
// Convert from Multi Byte to utf-16
|
||||
std::string mb_string(e.what());
|
||||
int size = MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), nullptr, 0);
|
||||
|
||||
std::wstring utf16_string(size, L'\0');
|
||||
MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), &*utf16_string.begin(), size);
|
||||
// Convert from utf-16 to utf-8
|
||||
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(utf16_string);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // fsbridge
|
||||
|
|
|
|||
23
src/fs.h
23
src/fs.h
|
|
@ -18,7 +18,28 @@ namespace fs = boost::filesystem;
|
|||
/** Bridge operations to C stdio */
|
||||
namespace fsbridge {
|
||||
FILE *fopen(const fs::path& p, const char *mode);
|
||||
FILE *freopen(const fs::path& p, const char *mode, FILE *stream);
|
||||
|
||||
class FileLock
|
||||
{
|
||||
public:
|
||||
FileLock() = delete;
|
||||
FileLock(const FileLock&) = delete;
|
||||
FileLock(FileLock&&) = delete;
|
||||
explicit FileLock(const fs::path& file);
|
||||
~FileLock();
|
||||
bool TryLock();
|
||||
std::string GetReason() { return reason; }
|
||||
|
||||
private:
|
||||
std::string reason;
|
||||
#ifndef WIN32
|
||||
int fd = -1;
|
||||
#else
|
||||
void* hFile = (void*)-1; // INVALID_HANDLE_VALUE
|
||||
#endif
|
||||
};
|
||||
|
||||
std::string get_filesystem_error_message(const fs::filesystem_error& e);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_FS_H
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <util.h>
|
||||
#include <utilstrencodings.h>
|
||||
#include <ui_interface.h>
|
||||
#include <walletinitinterface.h>
|
||||
#include <crypto/hmac_sha256.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
|
@ -240,10 +241,9 @@ bool StartHTTPRPC()
|
|||
return false;
|
||||
|
||||
RegisterHTTPHandler("/", true, HTTPReq_JSONRPC);
|
||||
#ifdef ENABLE_WALLET
|
||||
// ifdef can be removed once we switch to better endpoint support and API versioning
|
||||
RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC);
|
||||
#endif
|
||||
if (g_wallet_init_interface.HasWalletSupport()) {
|
||||
RegisterHTTPHandler("/wallet/", false, HTTPReq_JSONRPC);
|
||||
}
|
||||
struct event_base* eventBase = EventBase();
|
||||
assert(eventBase);
|
||||
httpRPCTimerInterface = MakeUnique<HTTPRPCTimerInterface>(eventBase);
|
||||
|
|
@ -260,9 +260,9 @@ void StopHTTPRPC()
|
|||
{
|
||||
LogPrint(BCLog::RPC, "Stopping HTTP RPC server\n");
|
||||
UnregisterHTTPHandler("/", true);
|
||||
#ifdef ENABLE_WALLET
|
||||
UnregisterHTTPHandler("/wallet/", false);
|
||||
#endif
|
||||
if (g_wallet_init_interface.HasWalletSupport()) {
|
||||
UnregisterHTTPHandler("/wallet/", false);
|
||||
}
|
||||
if (httpRPCTimerInterface) {
|
||||
RPCUnsetTimerInterface(httpRPCTimerInterface.get());
|
||||
httpRPCTimerInterface.reset();
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class WorkQueue
|
|||
{
|
||||
private:
|
||||
/** Mutex protects entire object */
|
||||
std::mutex cs;
|
||||
Mutex cs;
|
||||
std::condition_variable cond;
|
||||
std::deque<std::unique_ptr<WorkItem>> queue;
|
||||
bool running;
|
||||
|
|
@ -88,7 +88,7 @@ public:
|
|||
/** Enqueue a work item */
|
||||
bool Enqueue(WorkItem* item)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(cs);
|
||||
LOCK(cs);
|
||||
if (queue.size() >= maxDepth) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ public:
|
|||
while (true) {
|
||||
std::unique_ptr<WorkItem> i;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(cs);
|
||||
WAIT_LOCK(cs, lock);
|
||||
while (running && queue.empty())
|
||||
cond.wait(lock);
|
||||
if (!running)
|
||||
|
|
@ -116,7 +116,7 @@ public:
|
|||
/** Interrupt and exit loops */
|
||||
void Interrupt()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(cs);
|
||||
LOCK(cs);
|
||||
running = false;
|
||||
cond.notify_all();
|
||||
}
|
||||
|
|
@ -536,7 +536,7 @@ HTTPRequest::~HTTPRequest()
|
|||
// evhttpd cleans up the request, as long as a reply was sent.
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr)
|
||||
std::pair<bool, std::string> HTTPRequest::GetHeader(const std::string& hdr) const
|
||||
{
|
||||
const struct evkeyvalq* headers = evhttp_request_get_input_headers(req);
|
||||
assert(headers);
|
||||
|
|
@ -606,7 +606,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
|
|||
req = nullptr; // transferred back to main thread
|
||||
}
|
||||
|
||||
CService HTTPRequest::GetPeer()
|
||||
CService HTTPRequest::GetPeer() const
|
||||
{
|
||||
evhttp_connection* con = evhttp_request_get_connection(req);
|
||||
CService peer;
|
||||
|
|
@ -620,12 +620,12 @@ CService HTTPRequest::GetPeer()
|
|||
return peer;
|
||||
}
|
||||
|
||||
std::string HTTPRequest::GetURI()
|
||||
std::string HTTPRequest::GetURI() const
|
||||
{
|
||||
return evhttp_request_get_uri(req);
|
||||
}
|
||||
|
||||
HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod()
|
||||
HTTPRequest::RequestMethod HTTPRequest::GetRequestMethod() const
|
||||
{
|
||||
switch (evhttp_request_get_command(req)) {
|
||||
case EVHTTP_REQ_GET:
|
||||
|
|
|
|||
|
|
@ -74,21 +74,21 @@ public:
|
|||
|
||||
/** Get requested URI.
|
||||
*/
|
||||
std::string GetURI();
|
||||
std::string GetURI() const;
|
||||
|
||||
/** Get CService (address:ip) for the origin of the http request.
|
||||
*/
|
||||
CService GetPeer();
|
||||
CService GetPeer() const;
|
||||
|
||||
/** Get request method.
|
||||
*/
|
||||
RequestMethod GetRequestMethod();
|
||||
RequestMethod GetRequestMethod() const;
|
||||
|
||||
/**
|
||||
* Get the request header specified by hdr, or an empty string.
|
||||
* Return a pair (isPresent,string).
|
||||
*/
|
||||
std::pair<bool, std::string> GetHeader(const std::string& hdr);
|
||||
std::pair<bool, std::string> GetHeader(const std::string& hdr) const;
|
||||
|
||||
/**
|
||||
* Read request body.
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ bool TxIndex::WriteBlock(const CBlock& block, const CBlockIndex* pindex)
|
|||
vPos.reserve(block.vtx.size());
|
||||
for (const auto& tx : block.vtx) {
|
||||
vPos.emplace_back(tx->GetHash(), pos);
|
||||
pos.nTxOffset += ::GetSerializeSize(*tx, SER_DISK, CLIENT_VERSION);
|
||||
pos.nTxOffset += ::GetSerializeSize(*tx, CLIENT_VERSION);
|
||||
}
|
||||
return m_db->WriteTxs(vPos);
|
||||
}
|
||||
|
|
|
|||
80
src/init.cpp
80
src/init.cpp
|
|
@ -53,13 +53,13 @@
|
|||
|
||||
#ifndef WIN32
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/interprocess/sync/file_lock.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
|
|
@ -78,33 +78,6 @@ static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
|
|||
std::unique_ptr<CConnman> g_connman;
|
||||
std::unique_ptr<PeerLogicValidation> peerLogic;
|
||||
|
||||
#if !(ENABLE_WALLET)
|
||||
class DummyWalletInit : public WalletInitInterface {
|
||||
public:
|
||||
|
||||
void AddWalletOptions() const override;
|
||||
bool ParameterInteraction() const override {return true;}
|
||||
void RegisterRPC(CRPCTable &) const override {}
|
||||
bool Verify() const override {return true;}
|
||||
bool Open() const override {LogPrintf("No wallet support compiled in!\n"); return true;}
|
||||
void Start(CScheduler& scheduler) const override {}
|
||||
void Flush() const override {}
|
||||
void Stop() const override {}
|
||||
void Close() const override {}
|
||||
};
|
||||
|
||||
void DummyWalletInit::AddWalletOptions() const
|
||||
{
|
||||
std::vector<std::string> opts = {"-addresstype", "-changetype", "-disablewallet", "-discardfee=<amt>", "-fallbackfee=<amt>",
|
||||
"-keypool=<n>", "-mintxfee=<amt>", "-paytxfee=<amt>", "-rescan", "-salvagewallet", "-spendzeroconfchange", "-txconfirmtarget=<n>",
|
||||
"-upgradewallet", "-wallet=<path>", "-walletbroadcast", "-walletdir=<dir>", "-walletnotify=<cmd>", "-walletrbf", "-zapwallettxes=<mode>",
|
||||
"-dblogsize=<n>", "-flushwallet", "-privdb", "-walletrejectlongchains"};
|
||||
gArgs.AddHiddenArgs(opts);
|
||||
}
|
||||
|
||||
const WalletInitInterface& g_wallet_init_interface = DummyWalletInit();
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
|
||||
// accessing block files don't count towards the fd_set size limit
|
||||
|
|
@ -347,8 +320,10 @@ void SetupServerArgs()
|
|||
{
|
||||
const auto defaultBaseParams = CreateBaseChainParams(CBaseChainParams::MAIN);
|
||||
const auto testnetBaseParams = CreateBaseChainParams(CBaseChainParams::TESTNET);
|
||||
const auto regtestBaseParams = CreateBaseChainParams(CBaseChainParams::REGTEST);
|
||||
const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
|
||||
const auto testnetChainParams = CreateChainParams(CBaseChainParams::TESTNET);
|
||||
const auto regtestChainParams = CreateChainParams(CBaseChainParams::REGTEST);
|
||||
|
||||
// Hidden Options
|
||||
std::vector<std::string> hidden_args = {"-rpcssl", "-benchmark", "-h", "-help", "-socks", "-tor", "-debugnet", "-whitelistalwaysrelay",
|
||||
|
|
@ -390,7 +365,7 @@ void SetupServerArgs()
|
|||
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
|
||||
"(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024), false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-reindex", "Rebuild chain state and block index from the blk*.dat files on disk", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks", false, OptionsCategory::OPTIONS);
|
||||
gArgs.AddArg("-reindex-chainstate", "Rebuild chain state from the currently indexed blocks. When in pruning mode or if blocks on disk might be corrupted, use full -reindex instead.", false, OptionsCategory::OPTIONS);
|
||||
#ifndef WIN32
|
||||
gArgs.AddArg("-sysperms", "Create new files with system default permissions, instead of umask 077 (only effective with disabled wallet functionality)", false, OptionsCategory::OPTIONS);
|
||||
#else
|
||||
|
|
@ -420,7 +395,7 @@ void SetupServerArgs()
|
|||
gArgs.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (ipv4, ipv6 or onion). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks.", false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u or testnet: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), false, OptionsCategory::CONNECTION);
|
||||
gArgs.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", false, OptionsCategory::CONNECTION);
|
||||
|
|
@ -455,9 +430,16 @@ void SetupServerArgs()
|
|||
#endif
|
||||
|
||||
gArgs.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is (0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u)", defaultChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u)", defaultChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: "
|
||||
"level 0 reads the blocks from disk, "
|
||||
"level 1 verifies block validity, "
|
||||
"level 2 verifies undo data, "
|
||||
"level 3 checks disconnection of tip blocks, "
|
||||
"and level 4 tries to reconnect the blocks, "
|
||||
"each level includes the checks of the previous levels "
|
||||
"(0-4, default: %u)", DEFAULT_CHECKLEVEL), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checkblockindex", strprintf("Do a full consistency check for mapBlockIndex, setBlockIndexCandidates, chainActive and mapBlocksUnlinked occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-checkpoints", strprintf("Disable expensive verification for known chain history (default: %u)", DEFAULT_CHECKPOINTS_ENABLED), true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", true, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-dropmessagestest=<n>", "Randomly drop 1 of every <n> network messages", true, OptionsCategory::DEBUG_TEST);
|
||||
|
|
@ -471,7 +453,7 @@ void SetupServerArgs()
|
|||
gArgs.AddArg("-debug=<category>", "Output debugging information (default: -nodebug, supplying <category> is optional). "
|
||||
"If <category> is not supplied or if <category> = 1, output all debugging information. <category> can be: " + ListLogCategories() + ".", false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-debugexclude=<category>", strprintf("Exclude debugging information for a category. Can be used in conjunction with -debug=1 to output debug logs for all categories except one or more specified categories."), false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-help-debug", "Show all debugging options (usage: --help -help-debug)", false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-help-debug", "Print help message with debugging options and exit", false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-logips", strprintf("Include IP addresses in debug output (default: %u)", DEFAULT_LOGIPS), false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-logtimestamps", strprintf("Prepend debug output with timestamp (default: %u)", DEFAULT_LOGTIMESTAMPS), false, OptionsCategory::DEBUG_TEST);
|
||||
gArgs.AddArg("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS), true, OptionsCategory::DEBUG_TEST);
|
||||
|
|
@ -511,7 +493,7 @@ void SetupServerArgs()
|
|||
gArgs.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u or testnet: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()), false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcserialversion", strprintf("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(1) (default: %d)", DEFAULT_RPC_SERIALIZE_VERSION), false, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), true, OptionsCategory::RPC);
|
||||
gArgs.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), false, OptionsCategory::RPC);
|
||||
|
|
@ -548,7 +530,7 @@ void SetupServerArgs()
|
|||
gArgs.AddArg("-mainchainrpccookiefile=<file>", "The bitcoind cookie auth path which the daemon will use to connect to the trusted bitcoind to validate peg-ins. (default: `<datadir>/regtest/.cookie`)", false, OptionsCategory::ELEMENTS);
|
||||
gArgs.AddArg("-mainchainrpctimeout=<n>", strprintf("Timeout in seconds during mainchain RPC requests, or 0 for no timeout. (default: %d)", DEFAULT_HTTP_CLIENT_TIMEOUT), false, OptionsCategory::ELEMENTS);
|
||||
gArgs.AddArg("-peginconfirmationdepth=<n>", strprintf("Pegin claims must be this deep to be considered valid. (default: %d)", DEFAULT_PEGIN_CONFIRMATION_DEPTH), false, OptionsCategory::ELEMENTS);
|
||||
gArgs.AddArg("-recheckpeginblockinterval=<n>", strprintf("The interval in seconds at which a peg-in witness failing block is re-evaluated in case of intermittant peg-in witness failure. 0 means never. (default: %u)", 120), false, OptionsCategory::ELEMENTS);
|
||||
gArgs.AddArg("-recheckpeginblockinterval=<n>", strprintf("The interval in seconds at which a peg-in witness failing block is re-evaluated in case of intermittent peg-in witness failure. 0 means never. (default: %u)", 120), false, OptionsCategory::ELEMENTS);
|
||||
gArgs.AddArg("-parentpubkeyprefix", strprintf("The byte prefix, in decimal, of the parent chain's base58 pubkey address. (default: %d)", 111), false, OptionsCategory::CHAINPARAMS);
|
||||
gArgs.AddArg("-parentscriptprefix", strprintf("The byte prefix, in decimal, of the parent chain's base58 script address. (default: %d)", 196), false, OptionsCategory::CHAINPARAMS);
|
||||
gArgs.AddArg("-parent_bech32_hrp", strprintf("The human-readable part of the parent chain's bech32 encoding. (default: %s)", "bc"), false, OptionsCategory::CHAINPARAMS);
|
||||
|
|
@ -594,17 +576,17 @@ static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex
|
|||
}
|
||||
|
||||
static bool fHaveGenesis = false;
|
||||
static CWaitableCriticalSection cs_GenesisWait;
|
||||
static CConditionVariable condvar_GenesisWait;
|
||||
static Mutex g_genesis_wait_mutex;
|
||||
static std::condition_variable g_genesis_wait_cv;
|
||||
|
||||
static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex)
|
||||
{
|
||||
if (pBlockIndex != nullptr) {
|
||||
{
|
||||
WaitableLock lock_GenesisWait(cs_GenesisWait);
|
||||
LOCK(g_genesis_wait_mutex);
|
||||
fHaveGenesis = true;
|
||||
}
|
||||
condvar_GenesisWait.notify_all();
|
||||
g_genesis_wait_cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1251,7 +1233,19 @@ bool AppInitMain()
|
|||
LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
|
||||
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
|
||||
LogPrintf("Using data directory %s\n", GetDataDir().string());
|
||||
LogPrintf("Using config file %s\n", GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
|
||||
|
||||
// Only log conf file usage message if conf file actually exists.
|
||||
fs::path config_file_path = GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME));
|
||||
if (fs::exists(config_file_path)) {
|
||||
LogPrintf("Config file: %s\n", config_file_path.string());
|
||||
} else if (gArgs.IsArgSet("-conf")) {
|
||||
// Warn if no conf file exists at path provided by user
|
||||
InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string()));
|
||||
} else {
|
||||
// Not categorizing as "Warning" because it's the default behavior
|
||||
LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
|
||||
}
|
||||
|
||||
LogPrintf("Using at most %i automatic connections (%i file descriptors available)\n", nMaxConnections, nFD);
|
||||
|
||||
// Warn about relative -datadir path.
|
||||
|
|
@ -1669,12 +1663,12 @@ bool AppInitMain()
|
|||
|
||||
// Wait for genesis block to be processed
|
||||
{
|
||||
WaitableLock lock(cs_GenesisWait);
|
||||
WAIT_LOCK(g_genesis_wait_mutex, lock);
|
||||
// We previously could hang here if StartShutdown() is called prior to
|
||||
// ThreadImport getting started, so instead we just wait on a timer to
|
||||
// check ShutdownRequested() regularly.
|
||||
while (!fHaveGenesis && !ShutdownRequested()) {
|
||||
condvar_GenesisWait.wait_for(lock, std::chrono::milliseconds(500));
|
||||
g_genesis_wait_cv.wait_for(lock, std::chrono::milliseconds(500));
|
||||
}
|
||||
uiInterface.NotifyBlockTip_disconnect(BlockNotifyGenesisWait);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,6 @@
|
|||
class CScheduler;
|
||||
class CWallet;
|
||||
|
||||
class WalletInitInterface;
|
||||
extern const WalletInitInterface& g_wallet_init_interface;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread_group;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace {
|
|||
class HandlerImpl : public Handler
|
||||
{
|
||||
public:
|
||||
HandlerImpl(boost::signals2::connection connection) : m_connection(std::move(connection)) {}
|
||||
explicit HandlerImpl(boost::signals2::connection connection) : m_connection(std::move(connection)) {}
|
||||
|
||||
void disconnect() override { m_connection.disconnect(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -32,19 +32,18 @@
|
|||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config/bitcoin-config.h>
|
||||
#endif
|
||||
#ifdef ENABLE_WALLET
|
||||
#include <wallet/fees.h>
|
||||
#include <wallet/wallet.h>
|
||||
#define CHECK_WALLET(x) x
|
||||
#else
|
||||
#define CHECK_WALLET(x) throw std::logic_error("Wallet function called in non-wallet build.")
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <univalue.h>
|
||||
|
||||
class CWallet;
|
||||
std::vector<std::shared_ptr<CWallet>> GetWallets();
|
||||
|
||||
namespace interfaces {
|
||||
|
||||
class Wallet;
|
||||
|
||||
namespace {
|
||||
|
||||
class NodeImpl : public Node
|
||||
|
|
@ -221,15 +220,11 @@ class NodeImpl : public Node
|
|||
}
|
||||
std::vector<std::unique_ptr<Wallet>> getWallets() override
|
||||
{
|
||||
#ifdef ENABLE_WALLET
|
||||
std::vector<std::unique_ptr<Wallet>> wallets;
|
||||
for (const std::shared_ptr<CWallet>& wallet : GetWallets()) {
|
||||
wallets.emplace_back(MakeWallet(wallet));
|
||||
}
|
||||
return wallets;
|
||||
#else
|
||||
throw std::logic_error("Node::getWallets() called in non-wallet build.");
|
||||
#endif
|
||||
}
|
||||
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
|
||||
{
|
||||
|
|
@ -249,8 +244,7 @@ class NodeImpl : public Node
|
|||
}
|
||||
std::unique_ptr<Handler> handleLoadWallet(LoadWalletFn fn) override
|
||||
{
|
||||
CHECK_WALLET(
|
||||
return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::shared_ptr<CWallet> wallet) { fn(MakeWallet(wallet)); })));
|
||||
return MakeHandler(::uiInterface.LoadWallet_connect([fn](std::shared_ptr<CWallet> wallet) { fn(MakeWallet(wallet)); }));
|
||||
}
|
||||
std::unique_ptr<Handler> handleNotifyNumConnectionsChanged(NotifyNumConnectionsChangedFn fn) override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace {
|
|||
class PendingWalletTxImpl : public PendingWalletTx
|
||||
{
|
||||
public:
|
||||
PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet), m_key(&wallet) {}
|
||||
explicit PendingWalletTxImpl(CWallet& wallet) : m_wallet(wallet), m_key(&wallet) {}
|
||||
|
||||
const CTransaction& get() override { return *m_tx; }
|
||||
|
||||
|
|
@ -39,12 +39,11 @@ public:
|
|||
|
||||
bool commit(WalletValueMap value_map,
|
||||
WalletOrderForm order_form,
|
||||
std::string from_account,
|
||||
std::string& reject_reason) override
|
||||
{
|
||||
LOCK2(cs_main, m_wallet.cs_wallet);
|
||||
CValidationState state;
|
||||
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), std::move(from_account), m_key, g_connman.get(), state)) {
|
||||
if (!m_wallet.CommitTransaction(m_tx, std::move(value_map), std::move(order_form), m_key, g_connman.get(), state)) {
|
||||
reject_reason = state.GetRejectReason();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -57,7 +56,7 @@ public:
|
|||
};
|
||||
|
||||
//! Construct wallet tx struct.
|
||||
WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
|
||||
static WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
WalletTx result;
|
||||
result.tx = wtx.tx;
|
||||
|
|
@ -85,7 +84,7 @@ WalletTx MakeWalletTx(CWallet& wallet, const CWalletTx& wtx)
|
|||
}
|
||||
|
||||
//! Construct wallet tx status struct.
|
||||
WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
|
||||
static WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
WalletTxStatus result;
|
||||
auto mi = ::mapBlockIndex.find(wtx.hashBlock);
|
||||
|
|
@ -104,7 +103,7 @@ WalletTxStatus MakeWalletTxStatus(const CWalletTx& wtx)
|
|||
}
|
||||
|
||||
//! Construct wallet TxOut struct.
|
||||
WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth)
|
||||
static WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int depth) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
WalletTxOut result;
|
||||
result.txout = wtx.tx->vout[n];
|
||||
|
|
@ -117,7 +116,7 @@ WalletTxOut MakeWalletTxOut(CWallet& wallet, const CWalletTx& wtx, int n, int de
|
|||
class WalletImpl : public Wallet
|
||||
{
|
||||
public:
|
||||
WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_shared_wallet(wallet), m_wallet(*wallet.get()) {}
|
||||
explicit WalletImpl(const std::shared_ptr<CWallet>& wallet) : m_shared_wallet(wallet), m_wallet(*wallet.get()) {}
|
||||
|
||||
bool encryptWallet(const SecureString& wallet_passphrase) override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -289,7 +289,6 @@ public:
|
|||
//! Send pending transaction and commit to wallet.
|
||||
virtual bool commit(WalletValueMap value_map,
|
||||
WalletOrderForm order_form,
|
||||
std::string from_account,
|
||||
std::string& reject_reason) = 0;
|
||||
};
|
||||
|
||||
|
|
@ -367,8 +366,8 @@ struct WalletTxOut
|
|||
bool is_spent = false;
|
||||
};
|
||||
|
||||
//! Return implementation of Wallet interface. This function will be undefined
|
||||
//! in builds where ENABLE_WALLET is false.
|
||||
//! Return implementation of Wallet interface. This function is defined in
|
||||
//! dummywallet.cpp and throws if the wallet component is not compiled.
|
||||
std::unique_ptr<Wallet> MakeWallet(const std::shared_ptr<CWallet>& wallet);
|
||||
|
||||
} // namespace interfaces
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static int ec_privkey_import_der(const secp256k1_context* ctx, unsigned char *ou
|
|||
* will be set to the number of bytes used in the buffer.
|
||||
* key32 must point to a 32-byte raw private key.
|
||||
*/
|
||||
static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, int compressed) {
|
||||
static int ec_privkey_export_der(const secp256k1_context *ctx, unsigned char *privkey, size_t *privkeylen, const unsigned char *key32, bool compressed) {
|
||||
assert(*privkeylen >= CKey::PRIVATE_KEY_SIZE);
|
||||
secp256k1_pubkey pubkey;
|
||||
size_t pubkeylen = 0;
|
||||
|
|
@ -170,7 +170,7 @@ CPrivKey CKey::GetPrivKey() const {
|
|||
size_t privkeylen;
|
||||
privkey.resize(PRIVATE_KEY_SIZE);
|
||||
privkeylen = PRIVATE_KEY_SIZE;
|
||||
ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed ? SECP256K1_EC_COMPRESSED : SECP256K1_EC_UNCOMPRESSED);
|
||||
ret = ec_privkey_export_der(secp256k1_context_sign, privkey.data(), &privkeylen, begin(), fCompressed);
|
||||
assert(ret);
|
||||
privkey.resize(privkeylen);
|
||||
return privkey;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ private:
|
|||
const bool for_parent;
|
||||
|
||||
public:
|
||||
DestinationEncoder(const CChainParams& params, const bool for_parent) : m_params(params), for_parent(for_parent) {}
|
||||
explicit DestinationEncoder(const CChainParams& params, const bool for_parent) : m_params(params), for_parent(for_parent) {}
|
||||
|
||||
std::string operator()(const CKeyID& id) const
|
||||
{
|
||||
|
|
@ -76,7 +76,7 @@ public:
|
|||
}
|
||||
|
||||
std::string operator()(const CNoDestination& no) const { return {}; }
|
||||
std::string operator()(const NullData& nd) const { return {}; }
|
||||
std::string operator()(const NullData& null) const { return {}; }
|
||||
};
|
||||
|
||||
CTxDestination DecodeDestination(const std::string& str, const CChainParams& params, const bool for_parent)
|
||||
|
|
|
|||
|
|
@ -219,13 +219,13 @@ void BCLog::Logger::LogPrintStr(const std::string &str)
|
|||
// reopen the log file, if requested
|
||||
if (m_reopen_file) {
|
||||
m_reopen_file = false;
|
||||
m_fileout = fsbridge::freopen(m_file_path, "a", m_fileout);
|
||||
if (!m_fileout) {
|
||||
return;
|
||||
FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
|
||||
if (new_fileout) {
|
||||
setbuf(new_fileout, nullptr); // unbuffered
|
||||
fclose(m_fileout);
|
||||
m_fileout = new_fileout;
|
||||
}
|
||||
setbuf(m_fileout, nullptr); // unbuffered
|
||||
}
|
||||
|
||||
FileWriteStr(strTimestamped, m_fileout);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,42 +125,31 @@ std::vector<CLogCategoryActive> ListActiveLogCategories();
|
|||
/** Return true if str parses as a log category and set the flag */
|
||||
bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str);
|
||||
|
||||
/** Get format string from VA_ARGS for error reporting */
|
||||
template<typename... Args> std::string FormatStringFromLogArgs(const char *fmt, const Args&... args) { return fmt; }
|
||||
|
||||
static inline void MarkUsed() {}
|
||||
template<typename T, typename... Args> static inline void MarkUsed(const T& t, const Args&... args)
|
||||
{
|
||||
(void)t;
|
||||
MarkUsed(args...);
|
||||
}
|
||||
|
||||
// Be conservative when using LogPrintf/error or other things which
|
||||
// unconditionally log to debug.log! It should not be the case that an inbound
|
||||
// peer can fill up a user's disk with debug.log entries.
|
||||
|
||||
#ifdef USE_COVERAGE
|
||||
#define LogPrintf(...) do { MarkUsed(__VA_ARGS__); } while(0)
|
||||
#define LogPrint(category, ...) do { MarkUsed(__VA_ARGS__); } while(0)
|
||||
#else
|
||||
#define LogPrintf(...) do { \
|
||||
if (g_logger->Enabled()) { \
|
||||
std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
|
||||
try { \
|
||||
_log_msg_ = tfm::format(__VA_ARGS__); \
|
||||
} catch (tinyformat::format_error &fmterr) { \
|
||||
/* Original format string will have newline so don't add one here */ \
|
||||
_log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \
|
||||
} \
|
||||
g_logger->LogPrintStr(_log_msg_); \
|
||||
} \
|
||||
} while(0)
|
||||
template <typename... Args>
|
||||
static inline void LogPrintf(const char* fmt, const Args&... args)
|
||||
{
|
||||
if (g_logger->Enabled()) {
|
||||
std::string log_msg;
|
||||
try {
|
||||
log_msg = tfm::format(fmt, args...);
|
||||
} catch (tinyformat::format_error& fmterr) {
|
||||
/* Original format string will have newline so don't add one here */
|
||||
log_msg = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt;
|
||||
}
|
||||
g_logger->LogPrintStr(log_msg);
|
||||
}
|
||||
}
|
||||
|
||||
#define LogPrint(category, ...) do { \
|
||||
if (LogAcceptCategory((category))) { \
|
||||
LogPrintf(__VA_ARGS__); \
|
||||
} \
|
||||
} while(0)
|
||||
#endif
|
||||
template <typename... Args>
|
||||
static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args)
|
||||
{
|
||||
if (LogAcceptCategory((category))) {
|
||||
LogPrintf(args...);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BITCOIN_LOGGING_H
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
// Pad block weight to account for OP_RETURN commitments with two compressed pubkeys
|
||||
for (const auto& commitment : commitments) {
|
||||
CTxOut output(0, commitment);
|
||||
nBlockWeight += ::GetSerializeSize(output, SER_NETWORK, PROTOCOL_VERSION)*WITNESS_SCALE_FACTOR;
|
||||
nBlockWeight += ::GetSerializeSize(output, PROTOCOL_VERSION)*WITNESS_SCALE_FACTOR;
|
||||
}
|
||||
// END PAK
|
||||
|
||||
|
|
|
|||
17
src/net.cpp
17
src/net.cpp
|
|
@ -344,7 +344,7 @@ CNode* CConnman::FindNode(const CService& addr)
|
|||
bool CConnman::CheckIncomingNonce(uint64_t nonce)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes) {
|
||||
for (const CNode* pnode : vNodes) {
|
||||
if (!pnode->fSuccessfullyConnected && !pnode->fInbound && pnode->GetLocalNonce() == nonce)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -715,6 +715,7 @@ void CNode::copyStats(CNodeStats &stats)
|
|||
X(nRecvBytes);
|
||||
}
|
||||
X(fWhitelisted);
|
||||
X(minFeeFilter);
|
||||
|
||||
// It is common for nodes with good ping times to suddenly become lagged,
|
||||
// due to a new block arriving or other large transfer.
|
||||
|
|
@ -1226,7 +1227,7 @@ void CConnman::ThreadSocketHandler()
|
|||
if(vNodesSize != nPrevNodeCount) {
|
||||
nPrevNodeCount = vNodesSize;
|
||||
if(clientInterface)
|
||||
clientInterface->NotifyNumConnectionsChanged(nPrevNodeCount);
|
||||
clientInterface->NotifyNumConnectionsChanged(vNodesSize);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1613,7 +1614,7 @@ void CConnman::ThreadDNSAddressSeed()
|
|||
|
||||
LOCK(cs_vNodes);
|
||||
int nRelevant = 0;
|
||||
for (auto pnode : vNodes) {
|
||||
for (const CNode* pnode : vNodes) {
|
||||
nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && !pnode->fOneShot && !pnode->m_manual_connection && !pnode->fInbound;
|
||||
}
|
||||
if (nRelevant >= 2) {
|
||||
|
|
@ -1732,7 +1733,7 @@ int CConnman::GetExtraOutboundCount()
|
|||
int nOutbound = 0;
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes) {
|
||||
for (const CNode* pnode : vNodes) {
|
||||
if (!pnode->fInbound && !pnode->m_manual_connection && !pnode->fFeeler && !pnode->fDisconnect && !pnode->fOneShot && pnode->fSuccessfullyConnected) {
|
||||
++nOutbound;
|
||||
}
|
||||
|
|
@ -1802,7 +1803,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||
std::set<std::vector<unsigned char> > setConnected;
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
for (CNode* pnode : vNodes) {
|
||||
for (const CNode* pnode : vNodes) {
|
||||
if (!pnode->fInbound && !pnode->m_manual_connection) {
|
||||
// Netgroups for inbound and addnode peers are not excluded because our goal here
|
||||
// is to not use multiple of our limited outbound slots on a single netgroup
|
||||
|
|
@ -2064,7 +2065,7 @@ void CConnman::ThreadMessageHandler()
|
|||
pnode->Release();
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(mutexMsgProc);
|
||||
WAIT_LOCK(mutexMsgProc, lock);
|
||||
if (!fMoreWork) {
|
||||
condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this] { return fMsgProcWake; });
|
||||
}
|
||||
|
|
@ -2166,7 +2167,7 @@ void Discover()
|
|||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
|
||||
// Get local host ip
|
||||
struct ifaddrs* myaddrs;
|
||||
if (getifaddrs(&myaddrs) == 0)
|
||||
|
|
@ -2346,7 +2347,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
|||
flagInterruptMsgProc = false;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutexMsgProc);
|
||||
LOCK(mutexMsgProc);
|
||||
fMsgProcWake = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -427,7 +427,7 @@ private:
|
|||
bool fMsgProcWake;
|
||||
|
||||
std::condition_variable condMsgProc;
|
||||
std::mutex mutexMsgProc;
|
||||
Mutex mutexMsgProc;
|
||||
std::atomic<bool> flagInterruptMsgProc;
|
||||
|
||||
CThreadInterrupt interruptNet;
|
||||
|
|
@ -558,6 +558,7 @@ public:
|
|||
double dPingTime;
|
||||
double dPingWait;
|
||||
double dMinPing;
|
||||
CAmount minFeeFilter;
|
||||
// Our address, as reported by the peer
|
||||
std::string addrLocal;
|
||||
// Address of this peer
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ struct COrphanTx {
|
|||
NodeId fromPeer;
|
||||
int64_t nTimeExpire;
|
||||
};
|
||||
static CCriticalSection g_cs_orphans;
|
||||
CCriticalSection g_cs_orphans;
|
||||
std::map<uint256, COrphanTx> mapOrphanTransactions GUARDED_BY(g_cs_orphans);
|
||||
|
||||
void EraseOrphansFor(NodeId peer);
|
||||
|
|
@ -442,7 +442,7 @@ static void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIV
|
|||
* lNodesAnnouncingHeaderAndIDs, and keeping that list under a certain size by
|
||||
* removing the first element if necessary.
|
||||
*/
|
||||
static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman)
|
||||
static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman* connman) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
CNodeState* nodestate = State(nodeid);
|
||||
|
|
@ -831,7 +831,7 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
|
|||
// active chain if they are no more than a month older (both in time, and in
|
||||
// best equivalent proof of work) than the best header chain we know about and
|
||||
// we fully-validated them at some point.
|
||||
static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams)
|
||||
static bool BlockRequestAllowed(const CBlockIndex* pindex, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
if (chainActive.Contains(pindex)) return true;
|
||||
|
|
@ -882,7 +882,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
|
|||
// Erase orphan transactions included or precluded by this block
|
||||
if (vOrphanErase.size()) {
|
||||
int nErased = 0;
|
||||
for (uint256 &orphanHash : vOrphanErase) {
|
||||
for (const uint256& orphanHash : vOrphanErase) {
|
||||
nErased += EraseOrphanTx(orphanHash);
|
||||
}
|
||||
LogPrint(BCLog::MEMPOOL, "Erased %d orphan tx included or conflicted by block\n", nErased);
|
||||
|
|
@ -1260,7 +1260,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
|
|||
}
|
||||
}
|
||||
|
||||
void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc)
|
||||
void static ProcessGetData(CNode* pfrom, const CChainParams& chainparams, CConnman* connman, const std::atomic<bool>& interruptMsgProc) LOCKS_EXCLUDED(cs_main)
|
||||
{
|
||||
AssertLockNotHeld(cs_main);
|
||||
|
||||
|
|
@ -1618,8 +1618,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
return true;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::VERSION)
|
||||
{
|
||||
if (strCommand == NetMsgType::VERSION) {
|
||||
// Each connection can only send one version message
|
||||
if (pfrom->nVersion != 0)
|
||||
{
|
||||
|
|
@ -1662,8 +1661,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
return false;
|
||||
}
|
||||
|
||||
if (nVersion < MIN_PEER_PROTO_VERSION)
|
||||
{
|
||||
if (nVersion < MIN_PEER_PROTO_VERSION) {
|
||||
// disconnect from peers older than this proto version
|
||||
LogPrint(BCLog::NET, "peer=%d using obsolete version %i; disconnecting\n", pfrom->GetId(), nVersion);
|
||||
if (enable_bip61) {
|
||||
|
|
@ -1674,8 +1672,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
return false;
|
||||
}
|
||||
|
||||
if (nVersion == 10300)
|
||||
nVersion = 300;
|
||||
if (!vRecv.empty())
|
||||
vRecv >> addrFrom >> nNonce;
|
||||
if (!vRecv.empty()) {
|
||||
|
|
@ -1796,9 +1792,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (pfrom->nVersion == 0)
|
||||
{
|
||||
if (pfrom->nVersion == 0) {
|
||||
// Must have a version message before anything else
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
|
|
@ -1842,18 +1836,17 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::SENDCMPCT, fAnnounceUsingCMPCTBLOCK, nCMPCTBLOCKVersion));
|
||||
}
|
||||
pfrom->fSuccessfullyConnected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (!pfrom->fSuccessfullyConnected)
|
||||
{
|
||||
if (!pfrom->fSuccessfullyConnected) {
|
||||
// Must have a verack message before anything else
|
||||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->GetId(), 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::ADDR)
|
||||
{
|
||||
if (strCommand == NetMsgType::ADDR) {
|
||||
std::vector<CAddress> vAddr;
|
||||
vRecv >> vAddr;
|
||||
|
||||
|
|
@ -1900,16 +1893,16 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
pfrom->fGetAddr = false;
|
||||
if (pfrom->fOneShot)
|
||||
pfrom->fDisconnect = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::SENDHEADERS)
|
||||
{
|
||||
if (strCommand == NetMsgType::SENDHEADERS) {
|
||||
LOCK(cs_main);
|
||||
State(pfrom->GetId())->fPreferHeaders = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::SENDCMPCT)
|
||||
{
|
||||
if (strCommand == NetMsgType::SENDCMPCT) {
|
||||
bool fAnnounceUsingCMPCTBLOCK = false;
|
||||
uint64_t nCMPCTBLOCKVersion = 0;
|
||||
vRecv >> fAnnounceUsingCMPCTBLOCK >> nCMPCTBLOCKVersion;
|
||||
|
|
@ -1929,11 +1922,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
State(pfrom->GetId())->fSupportsDesiredCmpctVersion = (nCMPCTBLOCKVersion == 1);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::INV)
|
||||
{
|
||||
if (strCommand == NetMsgType::INV) {
|
||||
std::vector<CInv> vInv;
|
||||
vRecv >> vInv;
|
||||
if (vInv.size() > MAX_INV_SZ)
|
||||
|
|
@ -1987,11 +1979,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::GETDATA)
|
||||
{
|
||||
if (strCommand == NetMsgType::GETDATA) {
|
||||
std::vector<CInv> vInv;
|
||||
vRecv >> vInv;
|
||||
if (vInv.size() > MAX_INV_SZ)
|
||||
|
|
@ -2009,11 +2000,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
|
||||
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
|
||||
ProcessGetData(pfrom, chainparams, connman, interruptMsgProc);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::GETBLOCKS)
|
||||
{
|
||||
if (strCommand == NetMsgType::GETBLOCKS) {
|
||||
CBlockLocator locator;
|
||||
uint256 hashStop;
|
||||
vRecv >> locator >> hashStop;
|
||||
|
|
@ -2078,11 +2068,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::GETBLOCKTXN)
|
||||
{
|
||||
if (strCommand == NetMsgType::GETBLOCKTXN) {
|
||||
BlockTransactionsRequest req;
|
||||
vRecv >> req;
|
||||
|
||||
|
|
@ -2128,11 +2117,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
assert(ret);
|
||||
|
||||
SendBlockTransactions(block, req, pfrom, connman);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::GETHEADERS)
|
||||
{
|
||||
if (strCommand == NetMsgType::GETHEADERS) {
|
||||
CBlockLocator locator;
|
||||
uint256 hashStop;
|
||||
vRecv >> locator >> hashStop;
|
||||
|
|
@ -2196,11 +2184,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
// in the SendMessages logic.
|
||||
nodestate->pindexBestHeaderSent = pindex ? pindex : chainActive.Tip();
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::HEADERS, vHeaders));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::TX)
|
||||
{
|
||||
if (strCommand == NetMsgType::TX) {
|
||||
// Stop processing the transaction early if
|
||||
// We are in blocks only mode and peer is either not whitelisted or whitelistrelay is off
|
||||
if (!fRelayTxes && (!pfrom->fWhitelisted || !gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)))
|
||||
|
|
@ -2301,7 +2288,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
}
|
||||
}
|
||||
|
||||
for (uint256 hash : vEraseQueue)
|
||||
for (const uint256& hash : vEraseQueue)
|
||||
EraseOrphanTx(hash);
|
||||
}
|
||||
else if (fMissingInputs)
|
||||
|
|
@ -2384,10 +2371,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
Misbehaving(pfrom->GetId(), nDoS);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||
if (strCommand == NetMsgType::CMPCTBLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||
{
|
||||
CBlockHeaderAndShortTxIDs cmpctblock;
|
||||
vRecv >> cmpctblock;
|
||||
|
|
@ -2605,10 +2592,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
MarkBlockAsReceived(pblock->GetHash());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||
if (strCommand == NetMsgType::BLOCKTXN && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||
{
|
||||
BlockTransactions resp;
|
||||
vRecv >> resp;
|
||||
|
|
@ -2680,10 +2667,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
mapBlockSource.erase(pblock->GetHash());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing
|
||||
if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing
|
||||
{
|
||||
std::vector<CBlockHeader> headers;
|
||||
|
||||
|
|
@ -2708,7 +2695,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
return ProcessHeadersMessage(pfrom, connman, headers, chainparams, should_punish);
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||
if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||
{
|
||||
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>();
|
||||
vRecv >> *pblock;
|
||||
|
|
@ -2734,11 +2721,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
LOCK(cs_main);
|
||||
mapBlockSource.erase(pblock->GetHash());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::GETADDR)
|
||||
{
|
||||
if (strCommand == NetMsgType::GETADDR) {
|
||||
// This asymmetric behavior for inbound and outbound connections was introduced
|
||||
// to prevent a fingerprinting attack: an attacker can send specific fake addresses
|
||||
// to users' AddrMan and later request them by sending getaddr messages.
|
||||
|
|
@ -2762,11 +2748,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
FastRandomContext insecure_rand;
|
||||
for (const CAddress &addr : vAddr)
|
||||
pfrom->PushAddress(addr, insecure_rand);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::MEMPOOL)
|
||||
{
|
||||
if (strCommand == NetMsgType::MEMPOOL) {
|
||||
if (!(pfrom->GetLocalServices() & NODE_BLOOM) && !pfrom->fWhitelisted)
|
||||
{
|
||||
LogPrint(BCLog::NET, "mempool request with bloom filters disabled, disconnect peer=%d\n", pfrom->GetId());
|
||||
|
|
@ -2783,11 +2768,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
|
||||
LOCK(pfrom->cs_inventory);
|
||||
pfrom->fSendMempool = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::PING)
|
||||
{
|
||||
if (strCommand == NetMsgType::PING) {
|
||||
if (pfrom->nVersion > BIP0031_VERSION)
|
||||
{
|
||||
uint64_t nonce = 0;
|
||||
|
|
@ -2805,11 +2789,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
// return very quickly.
|
||||
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::PONG, nonce));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::PONG)
|
||||
{
|
||||
if (strCommand == NetMsgType::PONG) {
|
||||
int64_t pingUsecEnd = nTimeReceived;
|
||||
uint64_t nonce = 0;
|
||||
size_t nAvail = vRecv.in_avail();
|
||||
|
|
@ -2862,11 +2845,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
if (bPingFinished) {
|
||||
pfrom->nPingNonceSent = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::FILTERLOAD)
|
||||
{
|
||||
if (strCommand == NetMsgType::FILTERLOAD) {
|
||||
CBloomFilter filter;
|
||||
vRecv >> filter;
|
||||
|
||||
|
|
@ -2883,11 +2865,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
pfrom->pfilter->UpdateEmptyFull();
|
||||
pfrom->fRelayTxes = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::FILTERADD)
|
||||
{
|
||||
if (strCommand == NetMsgType::FILTERADD) {
|
||||
std::vector<unsigned char> vData;
|
||||
vRecv >> vData;
|
||||
|
||||
|
|
@ -2908,19 +2889,19 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
LOCK(cs_main);
|
||||
Misbehaving(pfrom->GetId(), 100);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::FILTERCLEAR)
|
||||
{
|
||||
if (strCommand == NetMsgType::FILTERCLEAR) {
|
||||
LOCK(pfrom->cs_filter);
|
||||
if (pfrom->GetLocalServices() & NODE_BLOOM) {
|
||||
pfrom->pfilter.reset(new CBloomFilter());
|
||||
}
|
||||
pfrom->fRelayTxes = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::FEEFILTER) {
|
||||
if (strCommand == NetMsgType::FEEFILTER) {
|
||||
CAmount newFeeFilter = 0;
|
||||
vRecv >> newFeeFilter;
|
||||
if (MoneyRange(newFeeFilter)) {
|
||||
|
|
@ -2930,24 +2911,21 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
}
|
||||
LogPrint(BCLog::NET, "received: feefilter of %s from peer=%d\n", CFeeRate(newFeeFilter).ToString(), pfrom->GetId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (strCommand == NetMsgType::NOTFOUND) {
|
||||
if (strCommand == NetMsgType::NOTFOUND) {
|
||||
// We do not care about the NOTFOUND message, but logging an Unknown Command
|
||||
// message would be undesirable as we transmit it ourselves.
|
||||
return true;
|
||||
}
|
||||
|
||||
else {
|
||||
// Ignore unknown commands for extensibility
|
||||
LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Ignore unknown commands for extensibility
|
||||
LogPrint(BCLog::NET, "Unknown command \"%s\" from peer=%d\n", SanitizeString(strCommand), pfrom->GetId());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61)
|
||||
static bool SendRejectsAndCheckIfBanned(CNode* pnode, CConnman* connman, bool enable_bip61) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
CNodeState &state = *State(pnode->GetId());
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100;
|
|||
/** Default number of orphan+recently-replaced txn to keep around for block reconstruction */
|
||||
static const unsigned int DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN = 100;
|
||||
/** Default for BIP61 (sending reject messages) */
|
||||
static constexpr bool DEFAULT_ENABLE_BIP61 = true;
|
||||
static constexpr bool DEFAULT_ENABLE_BIP61{false};
|
||||
|
||||
class PeerLogicValidation final : public CValidationInterface, public NetEventsInterface {
|
||||
private:
|
||||
|
|
@ -61,7 +61,7 @@ public:
|
|||
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
|
||||
|
||||
/** Consider evicting an outbound peer based on the amount of time they've been behind our tip */
|
||||
void ConsiderEviction(CNode *pto, int64_t time_in_seconds);
|
||||
void ConsiderEviction(CNode *pto, int64_t time_in_seconds) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
/** Evict extra outbound peers. If we think our tip may be stale, connect to an extra outbound */
|
||||
void CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams);
|
||||
/** If we have extra outbound peers, try to disconnect the one with the oldest block announcement */
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
|
||||
#ifndef WIN32
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <codecvt>
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
|
||||
|
||||
#if !defined(MSG_NOSIGNAL)
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
|
@ -37,7 +37,7 @@ static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
|
|||
static std::atomic<bool> interruptSocks5Recv(false);
|
||||
|
||||
enum Network ParseNetwork(std::string net) {
|
||||
boost::to_lower(net);
|
||||
Downcase(net);
|
||||
if (net == "ipv4") return NET_IPV4;
|
||||
if (net == "ipv6") return NET_IPV6;
|
||||
if (net == "onion") return NET_ONION;
|
||||
|
|
@ -651,13 +651,13 @@ bool LookupSubNet(const char* pszName, CSubNet& ret)
|
|||
#ifdef WIN32
|
||||
std::string NetworkErrorString(int err)
|
||||
{
|
||||
char buf[256];
|
||||
wchar_t buf[256];
|
||||
buf[0] = 0;
|
||||
if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||
nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
buf, sizeof(buf), nullptr))
|
||||
buf, ARRAYSIZE(buf), nullptr))
|
||||
{
|
||||
return strprintf("%s (%d)", buf, err);
|
||||
return strprintf("%s (%d)", std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().to_bytes(buf), err);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@
|
|||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
static bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
|
||||
#include <boost/signals2/connection.hpp>
|
||||
|
||||
bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style)
|
||||
{
|
||||
bool fSecure = style & CClientUIInterface::SECURE;
|
||||
style &= ~CClientUIInterface::SECURE;
|
||||
|
|
@ -39,19 +41,18 @@ static bool noui_ThreadSafeMessageBox(const std::string& message, const std::str
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style)
|
||||
bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style)
|
||||
{
|
||||
return noui_ThreadSafeMessageBox(message, caption, style);
|
||||
}
|
||||
|
||||
static void noui_InitMessage(const std::string& message)
|
||||
void noui_InitMessage(const std::string& message)
|
||||
{
|
||||
LogPrintf("init message: %s\n", message);
|
||||
}
|
||||
|
||||
void noui_connect()
|
||||
{
|
||||
// Connect bitcoind signal handlers
|
||||
uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox);
|
||||
uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion);
|
||||
uiInterface.InitMessage_connect(noui_InitMessage);
|
||||
|
|
|
|||
12
src/noui.h
12
src/noui.h
|
|
@ -5,6 +5,16 @@
|
|||
#ifndef BITCOIN_NOUI_H
|
||||
#define BITCOIN_NOUI_H
|
||||
|
||||
extern void noui_connect();
|
||||
#include <string>
|
||||
|
||||
/** Non-GUI handler, which logs and prints messages. */
|
||||
bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& caption, unsigned int style);
|
||||
/** Non-GUI handler, which logs and prints questions. */
|
||||
bool noui_ThreadSafeQuestion(const std::string& /* ignored interactive message */, const std::string& message, const std::string& caption, unsigned int style);
|
||||
/** Non-GUI handler, which only logs a message. */
|
||||
void noui_InitMessage(const std::string& message);
|
||||
|
||||
/** Connect all bitcoind signal handlers */
|
||||
void noui_connect();
|
||||
|
||||
#endif // BITCOIN_NOUI_H
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ bool GetAmountFromParentChainPegin(CAmount& amount, const CTransaction& txBTC, u
|
|||
// return false;
|
||||
//}
|
||||
//amount = txBTC.vout[nOut].nValue.GetAmount();
|
||||
//TODO(rebase) reenable above for CA/CT
|
||||
//TODO(rebase) re-enable above for CA/CT
|
||||
amount = txBTC.vout[nOut].nValue;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -228,9 +228,10 @@ bool CheckParentProofOfWork(uint256 hash, unsigned int nBits, const Consensus::P
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& prevout, bool check_depth) {
|
||||
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& prevout, std::string& err_msg, bool check_depth) {
|
||||
// 0) Return false if !consensus.has_parent_chain
|
||||
if (!Params().GetConsensus().has_parent_chain) {
|
||||
err_msg = "Parent chain is not enabled on this network.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -249,6 +250,7 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
const std::vector<std::vector<unsigned char> >& stack = pegin_witness.stack;
|
||||
// Must include all elements
|
||||
if (stack.size() != 6) {
|
||||
err_msg = "Not enough stack items.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -257,15 +259,18 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
try {
|
||||
stream >> value;
|
||||
} catch (...) {
|
||||
err_msg = "Could not deserialize value.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!MoneyRange(value)) {
|
||||
err_msg = "Value was not in valid value range.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get asset type
|
||||
if (stack[1].size() != 32) {
|
||||
err_msg = "Asset type was not 32 bytes.";
|
||||
return false;
|
||||
}
|
||||
//TODO(rebase) CA
|
||||
|
|
@ -273,6 +278,7 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
|
||||
// Get genesis blockhash
|
||||
if (stack[2].size() != 32) {
|
||||
err_msg = "Parent genesis blockchaash was not 32 bytes.";
|
||||
return false;
|
||||
}
|
||||
uint256 gen_hash(stack[2]);
|
||||
|
|
@ -280,6 +286,7 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
// Get claim_script, sanity check size
|
||||
CScript claim_script(stack[3].begin(), stack[3].end());
|
||||
if (claim_script.size() > 100) {
|
||||
err_msg = "Claim script is too large.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -290,14 +297,17 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
if (Params().GetConsensus().ParentChainHasPow()) {
|
||||
Sidechain::Bitcoin::CMerkleBlock merkle_block_pow;
|
||||
if (!GetBlockAndTxFromMerkleBlock(block_hash, tx_hash, merkle_block_pow, stack[5])) {
|
||||
err_msg = "Could not extract block and tx from merkleblock.";
|
||||
return false;
|
||||
}
|
||||
if (!CheckParentProofOfWork(block_hash, merkle_block_pow.header.nBits, Params().GetConsensus())) {
|
||||
err_msg = "Parent proof of work is invalid or insufficient.";
|
||||
return false;
|
||||
}
|
||||
|
||||
Sidechain::Bitcoin::CTransactionRef pegtx;
|
||||
if (!CheckPeginTx(stack[4], pegtx, prevout, value, claim_script)) {
|
||||
err_msg = "Peg-in tx is invalid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -305,15 +315,18 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
} else {
|
||||
CMerkleBlock merkle_block;
|
||||
if (!GetBlockAndTxFromMerkleBlock(block_hash, tx_hash, merkle_block, stack[5])) {
|
||||
err_msg = "Could not extract block and tx from merkleblock.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckProofSignedParent(merkle_block.header, Params().GetConsensus())) {
|
||||
err_msg = "Parent signed block is invalid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
CTransactionRef pegtx;
|
||||
if (!CheckPeginTx(stack[4], pegtx, prevout, value, claim_script)) {
|
||||
err_msg = "Peg-in tx is invalid.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -322,11 +335,13 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
|
||||
// Check that the merkle proof corresponds to the txid
|
||||
if (prevout.hash != tx_hash) {
|
||||
err_msg = "Merkle proof and txid mismatch.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the genesis block corresponds to a valid peg (only one for now)
|
||||
if (gen_hash != Params().ParentGenesisBlockHash()) {
|
||||
err_msg = "Parent genesis block mismatch.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -339,6 +354,7 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
|
|||
// Finally, validate peg-in via rpc call
|
||||
if (check_depth && gArgs.GetBoolArg("-validatepegin", DEFAULT_VALIDATE_PEGIN)) {
|
||||
if (!IsConfirmedBitcoinBlock(block_hash, Params().GetConsensus().pegin_min_depth, num_txs)) {
|
||||
err_msg = "Needs more confirmations.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ bool GetAmountFromParentChainPegin(CAmount& amount, const CTransaction& txBTC, u
|
|||
/** Check whether a parent chain block hash satisfies the proof-of-work requirement specified by nBits */
|
||||
bool CheckParentProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&);
|
||||
/** Checks pegin witness for validity */
|
||||
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& prevout, bool check_depth = true);
|
||||
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& prevout, std::string& err_msg, bool check_depth);
|
||||
// Constructs unblinded output to be used in amount and scriptpubkey checks during pegin
|
||||
CTxOut GetPeginOutputFromWitness(const CScriptWitness& pegin_witness);
|
||||
|
||||
|
|
|
|||
|
|
@ -22,51 +22,6 @@ class CTxMemPoolEntry;
|
|||
class CTxMemPool;
|
||||
class TxConfirmStats;
|
||||
|
||||
/** \class CBlockPolicyEstimator
|
||||
* The BlockPolicyEstimator is used for estimating the feerate needed
|
||||
* for a transaction to be included in a block within a certain number of
|
||||
* blocks.
|
||||
*
|
||||
* At a high level the algorithm works by grouping transactions into buckets
|
||||
* based on having similar feerates and then tracking how long it
|
||||
* takes transactions in the various buckets to be mined. It operates under
|
||||
* the assumption that in general transactions of higher feerate will be
|
||||
* included in blocks before transactions of lower feerate. So for
|
||||
* example if you wanted to know what feerate you should put on a transaction to
|
||||
* be included in a block within the next 5 blocks, you would start by looking
|
||||
* at the bucket with the highest feerate transactions and verifying that a
|
||||
* sufficiently high percentage of them were confirmed within 5 blocks and
|
||||
* then you would look at the next highest feerate bucket, and so on, stopping at
|
||||
* the last bucket to pass the test. The average feerate of transactions in this
|
||||
* bucket will give you an indication of the lowest feerate you can put on a
|
||||
* transaction and still have a sufficiently high chance of being confirmed
|
||||
* within your desired 5 blocks.
|
||||
*
|
||||
* Here is a brief description of the implementation:
|
||||
* When a transaction enters the mempool, we track the height of the block chain
|
||||
* at entry. All further calculations are conducted only on this set of "seen"
|
||||
* transactions. Whenever a block comes in, we count the number of transactions
|
||||
* in each bucket and the total amount of feerate paid in each bucket. Then we
|
||||
* calculate how many blocks Y it took each transaction to be mined. We convert
|
||||
* from a number of blocks to a number of periods Y' each encompassing "scale"
|
||||
* blocks. This is tracked in 3 different data sets each up to a maximum
|
||||
* number of periods. Within each data set we have an array of counters in each
|
||||
* feerate bucket and we increment all the counters from Y' up to max periods
|
||||
* representing that a tx was successfully confirmed in less than or equal to
|
||||
* that many periods. We want to save a history of this information, so at any
|
||||
* time we have a counter of the total number of transactions that happened in a
|
||||
* given feerate bucket and the total number that were confirmed in each of the
|
||||
* periods or less for any bucket. We save this history by keeping an
|
||||
* exponentially decaying moving average of each one of these stats. This is
|
||||
* done for a different decay in each of the 3 data sets to keep relevant data
|
||||
* from different time horizons. Furthermore we also keep track of the number
|
||||
* unmined (in mempool or left mempool without being included in a block)
|
||||
* transactions in each bucket and for how many blocks they have been
|
||||
* outstanding and use both of these numbers to increase the number of transactions
|
||||
* we've seen in that feerate bucket when calculating an estimate for any number
|
||||
* of confirmations below the number of blocks they've been outstanding.
|
||||
*/
|
||||
|
||||
/* Identifier for each of the 3 different TxConfirmStats which will track
|
||||
* history over different time horizons. */
|
||||
enum class FeeEstimateHorizon {
|
||||
|
|
@ -130,7 +85,50 @@ struct FeeCalculation
|
|||
int returnedTarget = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
/** \class CBlockPolicyEstimator
|
||||
* The BlockPolicyEstimator is used for estimating the feerate needed
|
||||
* for a transaction to be included in a block within a certain number of
|
||||
* blocks.
|
||||
*
|
||||
* At a high level the algorithm works by grouping transactions into buckets
|
||||
* based on having similar feerates and then tracking how long it
|
||||
* takes transactions in the various buckets to be mined. It operates under
|
||||
* the assumption that in general transactions of higher feerate will be
|
||||
* included in blocks before transactions of lower feerate. So for
|
||||
* example if you wanted to know what feerate you should put on a transaction to
|
||||
* be included in a block within the next 5 blocks, you would start by looking
|
||||
* at the bucket with the highest feerate transactions and verifying that a
|
||||
* sufficiently high percentage of them were confirmed within 5 blocks and
|
||||
* then you would look at the next highest feerate bucket, and so on, stopping at
|
||||
* the last bucket to pass the test. The average feerate of transactions in this
|
||||
* bucket will give you an indication of the lowest feerate you can put on a
|
||||
* transaction and still have a sufficiently high chance of being confirmed
|
||||
* within your desired 5 blocks.
|
||||
*
|
||||
* Here is a brief description of the implementation:
|
||||
* When a transaction enters the mempool, we track the height of the block chain
|
||||
* at entry. All further calculations are conducted only on this set of "seen"
|
||||
* transactions. Whenever a block comes in, we count the number of transactions
|
||||
* in each bucket and the total amount of feerate paid in each bucket. Then we
|
||||
* calculate how many blocks Y it took each transaction to be mined. We convert
|
||||
* from a number of blocks to a number of periods Y' each encompassing "scale"
|
||||
* blocks. This is tracked in 3 different data sets each up to a maximum
|
||||
* number of periods. Within each data set we have an array of counters in each
|
||||
* feerate bucket and we increment all the counters from Y' up to max periods
|
||||
* representing that a tx was successfully confirmed in less than or equal to
|
||||
* that many periods. We want to save a history of this information, so at any
|
||||
* time we have a counter of the total number of transactions that happened in a
|
||||
* given feerate bucket and the total number that were confirmed in each of the
|
||||
* periods or less for any bucket. We save this history by keeping an
|
||||
* exponentially decaying moving average of each one of these stats. This is
|
||||
* done for a different decay in each of the 3 data sets to keep relevant data
|
||||
* from different time horizons. Furthermore we also keep track of the number
|
||||
* unmined (in mempool or left mempool without being included in a block)
|
||||
* transactions in each bucket and for how many blocks they have been
|
||||
* outstanding and use both of these numbers to increase the number of transactions
|
||||
* we've seen in that feerate bucket when calculating an estimate for any number
|
||||
* of confirmations below the number of blocks they've been outstanding.
|
||||
*
|
||||
* We want to be able to estimate feerates that are needed on tx's to be included in
|
||||
* a certain number of blocks. Every time a block is added to the best chain, this class records
|
||||
* stats on the transactions included in that block
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
|||
if (txout.scriptPubKey.IsUnspendable())
|
||||
return 0;
|
||||
|
||||
size_t nSize = GetSerializeSize(txout, SER_DISK, 0);
|
||||
size_t nSize = GetSerializeSize(txout);
|
||||
int witnessversion = 0;
|
||||
std::vector<unsigned char> witnessprogram;
|
||||
|
||||
|
|
@ -59,12 +59,12 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
|||
bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
|
||||
{
|
||||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
if (!Solver(scriptPubKey, whichType, vSolutions))
|
||||
return false;
|
||||
whichType = Solver(scriptPubKey, vSolutions);
|
||||
|
||||
CChainParams params = Params();
|
||||
if (whichType == TX_MULTISIG)
|
||||
{
|
||||
if (whichType == TX_NONSTANDARD || whichType == TX_WITNESS_UNKNOWN) {
|
||||
return false;
|
||||
} else if (whichType == TX_MULTISIG) {
|
||||
unsigned char m = vSolutions.front()[0];
|
||||
unsigned char n = vSolutions.back()[0];
|
||||
// Support up to x-of-3 multisig txns as standard
|
||||
|
|
@ -77,10 +77,11 @@ bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
|
|||
// If we're enforcing pak let through larger peg-out scripts
|
||||
return true;
|
||||
} else if (whichType == TX_NULL_DATA &&
|
||||
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes))
|
||||
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return whichType != TX_NONSTANDARD && whichType != TX_WITNESS_UNKNOWN;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
||||
|
|
@ -188,14 +189,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
|
||||
|
||||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
txnouttype whichType;
|
||||
// get the scriptPubKey corresponding to this input:
|
||||
const CScript& prevScript = prev.scriptPubKey;
|
||||
if (!Solver(prevScript, whichType, vSolutions))
|
||||
txnouttype whichType = Solver(prev.scriptPubKey, vSolutions);
|
||||
if (whichType == TX_NONSTANDARD) {
|
||||
return false;
|
||||
|
||||
if (whichType == TX_SCRIPTHASH)
|
||||
{
|
||||
} else if (whichType == TX_SCRIPTHASH) {
|
||||
std::vector<std::vector<unsigned char> > stack;
|
||||
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue