rewrite ./vendor-libsecp.sh

This rewrite:
   * Fixes some shellcheck issues (bad quoting, use of | instead of ||
     near the beginning of the file)
   * Automatically computes the version prefix, depend directory, etc.,
     and provides instructions to override this with env vars if the
     user really wants to do this.
   * Detects when it would be destructive and refuses to run unless
     passed the -f flag, rather than prompting the user for a yes/no
   * Adds the capability to use cp rather than git clone, which I need
     to run this from within Nix.
   * Whitelists CHANGELOG.md which shouldn't get substituted.
This commit is contained in:
Andrew Poelstra 2023-03-29 23:21:36 +00:00
parent b7e38eb1e2
commit b58a60fd6c
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
1 changed files with 96 additions and 49 deletions

View File

@ -1,42 +1,92 @@
#!/bin/bash #!/usr/bin/env bash
set -e set -e
# Set default variables
: "${SECP_VENDOR_GIT_ROOT:=$(git rev-parse --show-toplevel)}"
SECP_SYS="$SECP_VENDOR_GIT_ROOT"/secp256k1-sys
DEFAULT_VERSION_CODE=$(grep version "$SECP_SYS/Cargo.toml" | sed 's/\./_/g' | sed 's/.*"\(.*\)".*/\1/')
DEFAULT_DEPEND_DIR="$SECP_SYS/depend"
DEFAULT_SECP_REPO=https://github.com/bitcoin-core/secp256k1.git
if [ -z "$1" ] | [ -z "$2" ]; then : "${SECP_VENDOR_VERSION_CODE:=$DEFAULT_VERSION_CODE}"
echo "\$1 parameter must be the rust-secp256k1-sys depend directory" : "${SECP_VENDOR_DEPEND_DIR:=$DEFAULT_DEPEND_DIR}"
echo "\$2 parameter must be the rust-secp256k1-sys version code (M_m_p format)" : "${SECP_VENDOR_SECP_REPO:=$DEFAULT_SECP_REPO}"
echo "\$3 parameter (optional) can be the revision to check out" # CP_NOT_CLONE lets us just copy a directory rather than git cloning.
exit 1 # This is usually a bad idea, since it will bring in build artifacts or any other
fi # junk from the source directory, but may be useful during development or CI.
: "${SECP_VENDOR_CP_NOT_CLONE:=no}"
PARENT_DIR=$1 echo "Using version code $SECP_VENDOR_VERSION_CODE. Set SECP_VENDOR_VERSION_CODE to override."
VERSIONCODE=$2 echo "Using depend directory $SECP_VENDOR_DEPEND_DIR. Set SECP_VENDOR_DEPEND_DIR to override."
REV=$3 echo "Using secp repository $SECP_VENDOR_SECP_REPO. Set SECP_VENDOR_SECP_REPO to override."
DIR=secp256k1
ORIGDIR=$(pwd)
while true; do # Parse command-line options
read -r -p "$PARENT_DIR/$DIR will be deleted [yn]: " yn SECP_REV=""
case $yn in FORCE=no
[Yy]* ) break;; while (( "$#" )); do
[Nn]* ) exit;; case "$1" in
* ) echo "Please answer yes or no.";; -f)
FORCE=yes
;;
*)
if [ -z "$SECP_REV" ]; then
echo "Using secp256k1 revision $SECP_REV."
SECP_REV="$1"
else
echo "WARNING: ignoring unknown command-line argument $1"
fi
;;
esac esac
shift
done done
cd "$PARENT_DIR" || exit 1 if [ -z "$SECP_REV" ]; then
rm -rf "$DIR" echo "WARNING: No secp256k1 revision specified. Will use whatever we find at the git repo."
git clone https://github.com/bitcoin-core/secp256k1.git "$DIR"
cd "$DIR"
if [ -n "$REV" ]; then
git checkout "$REV"
fi fi
HEAD=$(git rev-parse HEAD) echo
cd ..
echo "# This file was automatically created by $0" > ./secp256k1-HEAD-revision.txt
echo "$HEAD" >> ./secp256k1-HEAD-revision.txt
# We need to make some source changes to the files. # Check if we will do anything destructive.
if [ "$FORCE" == "no" ]; then
if ! git diff --quiet -- "*.rs"; then
echo "ERROR: There appear to be modified source files. Check these in or pass -f (some source files will be modified to have symbols renamed)."
exit 2
fi
if ! git diff --quiet -- "$SECP_VENDOR_DEPEND_DIR"; then
echo "ERROR: The depend directory appears to be modified. Check it in or pass -f (this directory will be deleted)."
exit 2
fi
fi
DIR=./secp256k1
pushd "$SECP_VENDOR_DEPEND_DIR" > /dev/null
rm -rf "$DIR" || true
# Clone the repo. As a special case, if the repo is a local path and we have
# not specified a revision, just copy the directory rather than using 'git clone'.
# This lets us use non-git repos or dirty source trees as secp sources.
if [ "$SECP_VENDOR_CP_NOT_CLONE" == "yes" ]; then
cp -r "$SECP_VENDOR_SECP_REPO" "$DIR"
chmod -R +w "$DIR" # cp preserves write perms, which if missing will cause patch to fail
else
git clone "$SECP_VENDOR_SECP_REPO" "$DIR"
fi
# Check out specified revision
pushd "$DIR" > /dev/null
if [ -n "$SECP_REV" ]; then
git checkout "$SECP_REV"
fi
SOURCE_REV=$(git rev-parse HEAD || echo "[unknown revision from $SECP_VENDOR_SECP_REPO]")
rm -rf .git/ || true
popd
# Record revision
echo "# This file was automatically created by $0" > ./secp256k1-HEAD-revision.txt
echo "$SOURCE_REV" >> ./secp256k1-HEAD-revision.txt
# Patch source files
# To support compiling for WASM, we need to remove all methods that use malloc. # To support compiling for WASM, we need to remove all methods that use malloc.
# To compensate, the secp_context_create and _destroy methods are redefined in Rust. # To compensate, the secp_context_create and _destroy methods are redefined in Rust.
@ -46,28 +96,25 @@ patch "$DIR/src/scratch_impl.h" "./scratch_impl.h.patch"
patch "$DIR/src/util.h" "./util.h.patch" patch "$DIR/src/util.h" "./util.h.patch"
# Prefix all methods with rustsecp and a version prefix # Prefix all methods with rustsecp and a version prefix
find "$DIR" -not -path '*/\.*' -type f -print0 | xargs -0 sed -i "/^#include/! s/secp256k1_/rustsecp256k1_v${VERSIONCODE}_/g" find "$DIR" \
-not -path '*/\.*' \
-not -name "CHANGELOG.md" \
-type f \
-print0 | xargs -0 sed -i "/^#include/! s/secp256k1_/rustsecp256k1_v${SECP_VENDOR_VERSION_CODE}_/g"
# special rule for a method that is not prefixed in libsecp # special rule for a method that is not prefixed in libsecp
find "$DIR" -not -path '*/\.*' -type f -print0 | xargs -0 sed -i "/^#include/! s/ecdsa_signature_parse_der_lax/rustsecp256k1_v${VERSIONCODE}_ecdsa_signature_parse_der_lax/g" find "$DIR" \
-not -path '*/\.*' \
# TODO: can be removed once 496c5b43b lands in secp-zkp -type f \
find "$DIR" -not -path '*/\.*' -type f -print0 | xargs -0 sed -i 's/^const int CURVE_B/static const int CURVE_B/g' -print0 | xargs -0 sed -i "/^#include/! s/ecdsa_signature_parse_der_lax/rustsecp256k1_v${SECP_VENDOR_VERSION_CODE}_ecdsa_signature_parse_der_lax/g"
while true; do
read -r -p "Update Rust extern references and Cargo.toml as well? [yn]: " yn
case $yn in
[Yy]* ) break;;
[Nn]* ) exit;;
* ) echo "Please answer yes or no.";;
esac
done
cd "$ORIGDIR"
cd "$SECP_SYS"
# Update the `links = ` in the manifest file. # Update the `links = ` in the manifest file.
sed -i -r "s/^links = \".*\"$/links = \"rustsecp256k1_v${VERSIONCODE}\"/" Cargo.toml sed -i -r "s/^links = \".*\"$/links = \"rustsecp256k1_v${SECP_VENDOR_VERSION_CODE}\"/" Cargo.toml
# Update the extern references in the Rust FFI source files. # Update the extern references in the Rust FFI source files.
find "./src/" -name "*.rs" -type f -print0 | xargs -0 sed -i -r "s/rustsecp256k1_v[0-9]+_[0-9]+_[0-9]+_(.*)([\"\(])/rustsecp256k1_v${VERSIONCODE}_\1\2/g" find "./src/" \
-name "*.rs" \
-type f \
-print0 | xargs -0 sed -i -r "s/rustsecp256k1_v[0-9]+_[0-9]+_[0-9]+_(.*)([\"\(])/rustsecp256k1_v${SECP_VENDOR_VERSION_CODE}_\1\2/g"
popd > /dev/null