diff --git a/rebase-and-rebuild.sh b/rebase-and-rebuild.sh deleted file mode 100755 index 3601abc3..00000000 --- a/rebase-and-rebuild.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -set -e - -commit_msg="Rebased, XORed, auto-update JAR" - -project=$( perl -n -e 'if (m/(\w+)<.artifactId>/) { print $1; exit }' pom.xml $) - -echo 'Checking for previous JAR commit to remove' -top_commit=$(git log -n 1 --format=%s) -if [ "${top_commit}" = "${commit_msg}" ]; then - echo 'Removing previous JAR commit' - git reset --hard HEAD^ - git push --force-with-lease -fi - -echo 'Rebasing using master branch' -git fetch -p origin -git rebase origin/master - -echo 'Pushing rebased branch' -git push --force-with-lease - -echo 'Building new XORed auto-update JAR' -mvn clean -mvn package -java -cp target/${project}*.jar org.qortal.XorUpdate target/${project}*.jar ${project}.update - -echo 'Pushing new JAR commit' -git add ${project}.update -git commit -m "${commit_msg}" -git push diff --git a/tools/build-auto-update.sh b/tools/build-auto-update.sh new file mode 100755 index 00000000..f012def9 --- /dev/null +++ b/tools/build-auto-update.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash + +set -e + +# Check we are within a git repo +git_dir=$( git rev-parse --show-toplevel ) +if [ -z "${git_dir}" ]; then + echo "Cannot determine top-level directory for git repo" + exit 1 +fi + +# Change to git top-level +cd ${git_dir} + +# Check we are in 'master' branch +branch_name=$( git symbolic-ref -q HEAD ) +branch_name=${branch_name##refs/heads/} +echo "Current git branch: ${branch_name}" +if [ "${branch_name}" != "master" ]; then + echo "Unexpected current branch '${branch_name}' - expecting 'master'" + exit 1 +fi + +# Extract short-form commit hash +short_hash=$( git rev-parse --short HEAD ) +if [ -z "${short_hash}" ]; then + echo "Unable to extract short-form current commit hash" + exit 1 +fi +echo "HEAD commit is: ${short_hash}" + +# Check there are no uncommitted changes +uncommitted=$( git status --short --untracked-files=no ) +if [ ! -z "${uncommitted}" ]; then + echo "Cannot continue due to uncommitted files:" + echo "${uncommitted}" + exit 1 +fi + +# Determine project name +project=$( perl -n -e 'if (m/(\w+)<.artifactId>/) { print $1; exit }' pom.xml $) +if [ -z "${project}" ]; then + echo "Unable to determine project name from pom.xml?" + exit 1 +fi + +# Actually rebuild JAR +echo "Building ${project} JAR..." +mvn clean package 1>/tmp/${project}-mvn-build.log 2>&1 +if [ "$?" != "0" -o ! -r target/${project}*.jar ]; then + echo "Maven build failed. For details, see /tmp/${project}-mvn-build.log" + exit 1 +fi + +# Convert packaged JAR to XORed update form +echo "Building ${project}.update..." +java -cp target/${project}*.jar org.qortal.XorUpdate target/${project}*.jar ${project}.update +if [ "$?" != "0" ]; then + echo "Failed to create XORed auto-update JAR" + exit 1 +fi + +# Create auto-update branch from this commit +update_branch=auto-update-${short_hash} + +if git show-ref --quiet --verify refs/heads/${update_branch}; then + echo "Existing auto-update branch based on this commit (${short_hash}) - deleting..." + git branch --delete --force ${update_branch} +fi + +echo "Checking out new auto-update branch based on this commit (${short_hash})..." +git checkout --orphan ${update_branch} +git rm --cached -fr . 1>/dev/null + +git add ${project}.update + +git commit --message "XORed, auto-update JAR based on commit ${short_hash}" +git push --set-upstream origin --force-with-lease ${update_branch} + +echo "Changing back to 'master' branch" +git checkout --force master diff --git a/broadcast-auto-update.pl b/tools/publish-auto-update.pl similarity index 51% rename from broadcast-auto-update.pl rename to tools/publish-auto-update.pl index b14d9e2b..b5d4d112 100755 --- a/broadcast-auto-update.pl +++ b/tools/publish-auto-update.pl @@ -1,5 +1,7 @@ #!/usr/bin/env perl +use strict; +use warnings; use POSIX; use Getopt::Std; @@ -15,6 +17,12 @@ usage() unless @ARGV == 1; my $port = $opt{p} || 12391; my $privkey = shift @ARGV; +my $git_dir = `git rev-parse --show-toplevel`; +die("Cannot determine git top level dir\n") unless $git_dir; + +chomp $git_dir; +chdir($git_dir) || die("Can't change directory to $git_dir: $!\n"); + open(POM, '<', 'pom.xml') || die ("Can't open 'pom.xml': $!\n"); my $project; while () { @@ -25,82 +33,90 @@ while () { } close(POM); -open(PROPS, '-|', 'unzip -p target/${project}*.jar build.properties') || die("Can't extract 'build.properties' from JAR: $!\n"); -while () { - if (m/build.timestamp=(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z/o) { - $timestamp = strftime('%s', $6, $5, $4, $3, $2 - 1, $1 - 1900, 0, 0, 0) * 1000; - last; - } -} -close(PROPS); - -die("Can't process build.timestamp\n") if ! defined $timestamp; - -$commit_hash = `git show --no-patch --format=%H`; - +# short-form commit hash on 'master' branch +my $commit_hash = `git show --no-patch --format=%h`; die("Can't find commit hash\n") if ! defined $commit_hash; chomp $commit_hash; +printf "Commit hash on 'master' branch: %s\n", $commit_hash; -$sha256sum = `sha256sum ${project}.update 2>/dev/null || sha256 ${project}.update 2>/dev/null`; +# build timestamp / commit timestamp on 'master' branch +my $timestamp = `git show --no-patch --format=%ct`; +die("Can't determine commit timestamp\n") if ! defined $timestamp; +$timestamp *= 1000; # Convert to milliseconds -die("Can't calculate SHA256 of ${project}.update\n") unless $sha256sum =~ m/(\S{64})/; +# locate sha256 utility +my $SHA256 = `which sha256sum || which sha256`; -$sha256 = $1; +# SHA256 of actual update file +my $sha256 = `git show auto-update-${commit_hash}:${project}.update | ${SHA256}`; +die("Can't calculate SHA256 of ${project}.update\n") unless $sha256 =~ m/(\S{64})/; +chomp $sha256; + +# long-form commit hash of HEAD on auto-update branch +my $update_hash = `git rev-parse refs/heads/auto-update-${commit_hash}`; +die("Can't find commit hash for HEAD on auto-update-${commit_hash} branch\n") if ! defined $update_hash; +chomp $update_hash; printf "Build timestamp (ms): %d / 0x%016x\n", $timestamp, $timestamp; -printf "Commit hash: %s\n", $commit_hash; +printf "Auto-update commit hash: %s\n", $update_hash; printf "SHA256 of ${project}.update: %s\n", $sha256; -$tx_type = 10; -$tx_timestamp = time() * 1000; -$tx_group_id = 1; -$service = 1; +my $tx_type = 10; +my $tx_timestamp = time() * 1000; +my $tx_group_id = 1; +my $service = 1; printf "\nARBITRARY(%d) transaction with timestamp %d, txGroupID %d and service %d\n", $tx_type, $tx_timestamp, $tx_group_id, $service; -$data = sprintf "%016x%s%s", $timestamp, $commit_hash, $sha256; -printf "\nARBITRARY transaction data payload: %s\n", $data; +my $data_hex = sprintf "%016x%s%s", $timestamp, $update_hash, $sha256; +printf "\nARBITRARY transaction data payload: %s\n", $data_hex; -$n_payments = 0; -$is_raw = 1; # RAW_DATA -$data_length = length($data) / 2; -$fee = 0.001 * 1e8; +my $n_payments = 0; +my $is_raw = 1; # RAW_DATA +my $data_length = length($data_hex) / 2; # two hex chars per byte +my $fee = 0.001 * 1e8; + +die("Something's wrong: data length is not 60 bytes!\n") if $data_length != 60; my $pubkey = `curl --silent --url http://localhost:${port}/utils/publickey --data ${privkey}`; -die("Can't convert private key to public key!\n") unless $pubkey; +die("Can't convert private key to public key:\n$pubkey\n") unless $pubkey =~ m/^\w{44}$/; printf "\nPublic key: %s\n", $pubkey; my $pubkey_hex = `curl --silent --url http://localhost:${port}/utils/frombase58 --data ${pubkey}`; +die("Can't convert base58 public key to hex:\n$pubkey_hex\n") unless $pubkey_hex =~ m/^[A-Za-z0-9]{64}$/; printf "Public key hex: %s\n", $pubkey_hex; my $address = `curl --silent --url http://localhost:${port}/addresses/convert/${pubkey}`; +die("Can't convert base58 public key to address:\n$address\n") unless $address =~ m/^\w{34}$/; printf "Address: %s\n", $address; my $reference = `curl --silent --url http://localhost:${port}/addresses/lastreference/${address}`; +die("Can't fetch last reference for $address:\n$reference\n") unless $reference =~ m/^\w{88}$/; printf "Last reference: %s\n", $reference; my $reference_hex = `curl --silent --url http://localhost:${port}/utils/frombase58 --data ${reference}`; +die("Can't convert base58 reference to hex:\n$reference_hex\n") unless $reference_hex =~ m/^[A-Za-z0-9]{128}$/; printf "Last reference hex: %s\n", $reference_hex; -my $raw_tx_hex = sprintf("%08x%016x%08x%s%s%08x%08x%02x%08x%s%016x", $tx_type, $tx_timestamp, $tx_group_id, $reference_hex, $pubkey_hex, $n_payments, $service, $is_raw, $data_length, $data, $fee); +my $raw_tx_hex = sprintf("%08x%016x%08x%s%s%08x%08x%02x%08x%s%016x", $tx_type, $tx_timestamp, $tx_group_id, $reference_hex, $pubkey_hex, $n_payments, $service, $is_raw, $data_length, $data_hex, $fee); printf "\nRaw transaction hex:\n%s\n", $raw_tx_hex; my $raw_tx = `curl --silent --url http://localhost:${port}/utils/tobase58/${raw_tx_hex}`; +die("Can't convert raw transaction hex to base58:\n$raw_tx\n") unless $raw_tx =~ m/^\w{255,265}$/; # Roughly 255 to 265 base58 chars printf "\nRaw transaction (base58):\n%s\n", $raw_tx; my $sign_data = qq|' { "privateKey": "${privkey}", "transactionBytes": "${raw_tx}" } '|; my $signed_tx = `curl --silent -H "accept: text/plain" -H "Content-Type: application/json" --url http://localhost:${port}/transactions/sign --data ${sign_data}`; +die("Can't sign raw transaction:\n$signed_tx\n") unless $signed_tx =~ m/^\w{345,355}$/; # +90ish longer than $raw_tx printf "\nSigned transaction:\n%s\n", $signed_tx; # Check we can actually fetch update my $origin = `git remote get-url origin`; die("Unable to get github url for 'origin'?\n") unless $origin && $origin =~ m/:(.*)\.git$/; my $repo = $1; -my $update_url = "https://github.com/${repo}/raw/${commit_hash}/${project}.update"; +my $update_url = "https://github.com/${repo}/raw/${update_hash}/${project}.update"; my $fetch_result = `curl --silent -o /dev/null --location --range 0-1 --head --write-out '%{http_code}' --url ${update_url}`; -if ($fetch_result ne '200') { - die("\nUnable to fetch update from ${update_url}\n"); -} +die("\nUnable to fetch update from ${update_url}\n") if $fetch_result ne '200'; printf "\nUpdate fetchable from ${update_url}\n"; # Flush STDOUT after every output @@ -113,4 +129,8 @@ for (my $delay = 5; $delay > 0; --$delay) { printf "\rSubmitting transaction NOW... \n"; my $result = `curl --silent --url http://localhost:${port}/transactions/process --data ${signed_tx}`; -printf "\nTransaction accepted: %s\n", $result; +chomp $result; +die("Transaction wasn't accepted:\n$result\n") unless $result eq 'true'; + +my $decoded_tx = `curl --silent -H "Content-Type: application/json" --url http://localhost:${port}/transactions/decode --data ${signed_tx}`; +printf "\nTransaction accepted:\n$decoded_tx\n"; \ No newline at end of file