#!/bin/sh # Download, verify and assemble source code for the Bitcoin reference implementation maintained by JWRD Computing. # Jacob Welsh, Nov 2021 set -e PATCHES_BASE=http://fixpoint.welshcomputing.com/v DEPS_BASE=http://fixpoint.welshcomputing.com/code/trb info() { printf '%s\n' "$1" printf '\n%s\n' "$1" >>"$LOG" } err() { printf '%s\n' "$1" >&2; } cmd_exists() { command -v "$1" >/dev/null; } require_cmd() { if ! cmd_exists "$1" ; then err "Required command '$1' not found." exit 1 fi } preflight_check() { # Check for nonstandard dependencies require_cmd wget require_cmd gpg HAVE_KEKSUM=1 if ! cmd_exists keksum ; then err "WARNING: 'keksum' command not found. Patch output hashes will not be verified before it's bootstrapped." HAVE_KEKSUM=0 fi if [ -e tree ] ; then err "Press directory $TOP/tree already exists! You must move or delete it to proceed." exit 1 fi } fail() { err "$1" err "See $LOG for detail." exit 1 } get() { # Ensure we have a file by downloading as necessary, preventing incomplete downloads. get_filename=`basename "$1"` if [ -e "$get_filename" ] ; then return 0 fi info "Fetching $get_filename ..." if ! wget -O "$TMP/download" "$1" >>"$LOG" 2>&1 ; then rm -f "$TMP/download" fail "Failed." fi mv -- "$TMP/download" "$get_filename" } get_patches_verify() { # Fetch and verify patches and seals. subdir=$1 mkdir -p patches ( cd patches while read basename signer ; do vp="$basename.vpatch" # If downloading from a one-level tree you could remove the $subdir here. get "$PATCHES_BASE/$subdir/$vp" # And if seals are in separate subdirs, adjust here. get "$PATCHES_BASE/$subdir/$vp.$signer.sig" gpg --verify "$vp.$signer.sig" "$vp" 2>>"$LOG" || fail "Signature verification failed for $vp !" done <"$TMP/press_path_$subdir" ) } get_deps() { # Fetch required depwads (non-V-ingested dependency tarballs). mkdir -p deps ( cd deps get "$DEPS_BASE/boost_1_52_0.tar.bz2" get "$DEPS_BASE/db-4.8.30.tar.gz" get "$DEPS_BASE/openssl-1.0.1g.tar.gz" ) } extract_hashes() { # Extract a listing of file path (omitting leading a/ or b/) and hash from each output header in a vpatch on stdin. awk ' /^diff/ { in_header = 1; next; } in_header && /^\+\+\+/ { in_header = 0; sub(/^[^\/]*\//, "", $2); print $2, $3; } ' } verify_hashes() { # Verify output hashes from a vpatch on stdin, with paths relative to the working directory. extract_hashes | while read path hash ; do if [ "$hash" = "false" ] ; then [ ! -e "$path" ] || fail "Patch failed to remove empty file $path !" elif [ $HAVE_KEKSUM -eq 1 ] ; then [ "`"$KEKSUM" -s256 -l512 <"$path"`" = "$hash" ] || fail "Hash verification failed on $path !" fi done } press() { # Apply trusted patches for a given project in the prescribed sequence, verifying their output file hashes. subdir=$1 info "Pressing $subdir ..." mkdir -p tree ( cd tree while read basename signer ; do vp="$basename.vpatch" printf '\nApplying %s\n' "$vp" >>"$LOG" patch -E -p1 <"../patches/$vp" >>"$LOG" 2>&1 || fail "Failed to apply $vp !" verify_hashes <"../patches/$vp" done <"$TMP/press_path_$subdir" ) } # Establish the top-level working directory. case "$1" in ''|-*) err "You must specify a top-level directory for the build environment. It will be created if necessary." err "Example:" err " sh $0 ~/src/bitcoin" exit 1 ;; esac mkdir -p "$1" cd "$1" TOP=`pwd` # absolute so it's usable from anywhere KEKSUM=keksum preflight_check # Set up temporary data tree, purging any left over from prior runs. TMP="$TOP/fetch-bitcoind.tmp" rm -rf "$TMP" mkdir "$TMP" LOG="$TMP/debug.log" export GNUPGHOME="$TMP/gpgdata" mkdir -m 700 "$GNUPGHOME" # Load patch signer keys: jfw, jfw_unchecked gpg --import 2>>"$LOG" <<. -----BEGIN PGP PUBLIC KEY BLOCK----- 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 9QMd/Rt5H3gtxri5J/zQJlzYCvkKng== =4dAK -----END PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBF59eScBEADHOi3Vt/gfq1TB4abvn7jxx0SRxINURjYWqoGJ8K16F9MoBC18 H9N+x1PMDzaGBghaFz1ERcgbGrFsA9LdZUSzJK6JtCjaI7P+XkX0CH+6Y+wRpNKk lObYvi6zanYSd4+JmqTkvRpTJavDjFKxL2xhixiwa2cTxAZVMFngIP5iZD+KulJg WOyBnwZ0OUeA24qXMy8ovBM6NsDzGPW/6bE6GxaHY/FT2vbmIPdI9RqeI2WxYuHm OcmFhaSnPuf8fAInJJc1Y/bc8rv//BfcWoDy60sDjkKgxfrden03FVRnTPBrNDcj P72BL/3hYan9xjx3hSkrOjX/JVPgnvxKgc/3YNk7MUMyBoRij397chJup9bbcGWU 4MopCDOpB504bzA4jwDEIMQxv8iBEF0lhv3/7Wc7jZzQ7Xyfeid9UVCQVdWyOil2 QmhGSa7sOcKCjR/qeHJIqbDeSAhIQTx057eBqj1f3xbW0X/YB6COhm6APsDXQWnX NNgDi9BIOfpS7TZ+tAnHIZpf9SdWcofBsE7sIG/G5L7iDsrY4KVIqcU2bv8sp0zE RpoAd9P9Am8GsysT+TMZe/ztfQG8DaKr8+88FCxwEl+C+HTeS+aYZ/+cm4DgS5yH mWWZ5UoubwVHCCMpI7G3JBNbT1mYP4ja6JzJFthttkfJn9kOldeWRc7u2QARAQAB tEVKYWNvYiBXZWxzaCAoamZ3X3VuY2hlY2tlZCAtIGluZGljYXRlcyBjb2RlIGJy b3VnaHQgaW4gZnJvbSB0aGUgd2lsZCmJAi4EEwECABgCGwMCHgECF4AFAl59ftwF CwkIBwMCFQoACgkQfpO9iVXJds49pxAAohOxvnxDTeK+20h5x1RxMI9TG/vC27Bu Il2RP/cUlC14w8QRZ15/zqboPOECmaYIUS+sdVtkr5DnQ8U5fO2vv7UluHYLqvN3 JUkfPOvrhs0Ga/yOq/7xV0r14X2eiR6FMncEWY7XZhKLshXOu3L4+IjsF1kbOUQZ c6/UvyOHQwXuh3ksebGCE1OJF16LH3u/b4rzb5mphNbx5Wwlb2T9/BQ0Nf7xkitD C7p1dL9GKk10M2V/FMgnZI9Bj1pY8ZlPjIh8EHs1VSBzh/95jt2VjHSbGW9lG3Zj EyV8XBcJwNM80rRBsY93JbgNOsx3wWtqc3oMHVmc7/Wta/IXrJP7jGdvVJSxaOQ+ aCWY5TXhOrfTm5quh9ny3DTgdyWd3nU6xfc0PIasSUPkrxrupDilldoyTF76bj0u 8SveUkpNAtxSzpj0X6rnxIb6nC2ivFx3vkB8kRhGBiY63Pk3MmM47GJW6r0sOZAn SGfMXTrdX3hjvIH5JzqwyEromrla4dh0oJiBK6qg2PxDckSl/8GNbaaczAEhM6mz 4QLfckXvyI8OApuuPGpW0PdzYhJfXUzt5RyAJYsxldonMqsfUKCMcw7aMa8kmk8l GArFxLhimBXO7JU7DvI4gOs6ny2PM9CW/lF2ux2CJwRkgOvl5FLKaagqSlM6rZmK QeJQS3RcbPE= =JTyf -----END PGP PUBLIC KEY BLOCK----- . # Load patch sequence and signer names for future reference. cat >"$TMP/press_path_keksum" <<. keksum_subdir_genesis jfw . cat >"$TMP/press_path_bitcoin" <<. genesis jfw_unchecked bitcoin-asciilifeform.1 jfw rm_rf_upnp jfw_unchecked bitcoin-asciilifeform.2-https_snipsnip jfw bitcoin-asciilifeform.3-turdmeister-alert-snip jfw_unchecked bitcoin-asciilifeform.4-goodbye-win32 jfw bitcoin-v0_5_3-db_config.6 jfw_unchecked bitcoin-v0_5_3_1-rev_bump.7 jfw bitcoin-v0_5_3_1-static_makefile_v002.8 jfw asciilifeform-kills-integer-retardation jfw_unchecked asciilifeform_and_now_we_have_block_dumper_corrected jfw_unchecked asciilifeform_dnsseed_snipsnip jfw asciilifeform_maxint_locks_corrected jfw_unchecked asciilifeform_orphanage_thermonuke jfw_unchecked asciilifeform_tx-orphanage_amputation jfw_unchecked asciilifeform_zap_hardcoded_seeds jfw asciilifeform_zap_showmyip_crud jfw_unchecked mod6_fix_dumpblock_params jfw_unchecked asciilifeform_dns_thermonyukyoolar_kleansing jfw asciilifeform_ver_now_5_4_and_irc_is_gone_and_now_must_give_ip jfw_unchecked asciilifeform_and_now_we_have_eatblock jfw_unchecked asciilifeform_lets_lose_testnet jfw_unchecked asciilifeform_add_verifyall_option jfw programmable-versionstring jfw_unchecked malleus_mikehearnificarum jfw mod6_der_high_low_s jfw_unchecked mod6_privkey_tools jfw_unchecked makefiles jfw asciilifeform_aggressive_pushgetblocks jfw_unchecked mod6_manifest jfw mod6_phexdigit_fix jfw mod6_excise_hash_truncation jfw mod6_whogaveblox jfw_unchecked bitcoin_rawtx_get_send jfw bitcoin_system_compiler jfw bitcoin_dumpblock_no_losers jfw bitcoin_help_tuneups jfw bitcoin_permissive_mode jfw bitcoin_boost_prune_built_libs jfw bitcoin_tx_fee_cleanup jfw bitcoin_fsync_all_blocks jfw bitcoin_checkblocks_cleanup jfw bitcoin_getblockindex_etc_corrected jfw bitcoin_drop_online_build jfw bitcoin_response_size_limits_1 jfw bitcoin_response_size_limits_2 jfw bitcoin_pushmessage_cleanup_1 jfw bitcoin_pushmessage_cleanup_2 jfw bitcoin_enforce_buffer_limits jfw bitcoin_posix_error_handling jfw bitcoin_rebranding jfw . cat >"$TMP/press_path_gscm" <<. gscm_subdir_genesis jfw gscm_fix_m_whitespace_package_install jfw gscm_immutable_fill jfw gscm_usrbin jfw gscm_glibc_build_fix jfw . cat >"$TMP/press_path_gbw-node" <<. gbw-node_subdir_genesis jfw gbw-node_usrbin jfw . cat >"$TMP/press_path_gbw-signer" <<. gbw-signer_subdir_genesis jfw gbw-signer_usrbin jfw gbw-signer_static_bit_ops_1 jfw gbw-signer_static_bit_ops_2 jfw gbw-signer_static_bit_ops_reindent jfw . get_patches_verify keksum get_patches_verify bitcoin get_patches_verify gscm get_patches_verify gbw-node get_patches_verify gbw-signer get_deps press keksum info "Building keksum ..." ( cd tree/keksum make >>"$LOG" 2>&1 || fail "Failed." ) KEKSUM="$TOP/tree/keksum/keksum" HAVE_KEKSUM=1 press bitcoin info 'Checking depwads ...' ( cd deps deplist=`awk '{print $2}' <../tree/bitcoin/deps/Manifest.keccak` "$KEKSUM" -s256 -l512 $deplist >"$TMP/deps.keccak" 2>>"$LOG" || fail "Failed." if ! diff "$TMP/deps.keccak" ../tree/bitcoin/deps/Manifest.keccak >>"$LOG" 2>&1 ; then err "Depwad verification failed!" err "Your downloaded tar files may be corrupt. Try removing them from $TOP/deps/ to re-download." fail fi ln $deplist ../tree/bitcoin/deps/ ) press gscm press gbw-node press gbw-signer info "Successfully pressed to $TOP/tree !" info "To build bitcoind, enter the tree/bitcoin subdir and run 'make'. (For faster results try 'make -jN' where N is the max concurrent job count.) For gscm, gbw-node, and gbw-signer, see the README in each respective subdir." # Cleanup on success. rm -rf "$TMP"