66 lines
2.4 KiB
Bash
Executable File
66 lines
2.4 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -euo pipefail
|
|
|
|
# Prints Zebra checkpoints, based on a list of block heights, sizes, ans hashes.
|
|
#
|
|
# Reads lines containing a block height, block byte size, and block header hash
|
|
# from stdin. Writes each checkpoint to stdout, as a line with space-separated
|
|
# fields.
|
|
#
|
|
# The block header hash is read in Bitcoin order, but written out in Zebra's
|
|
# internal byte order.
|
|
#
|
|
# Usage: get-height-size-hash.sh | calculate-checkpoints.sh
|
|
# get-height-size-hash.sh -testnet | calculate-checkpoints.sh
|
|
#
|
|
# calculate-checkpoints.sh ignores any command-line arguments.
|
|
#
|
|
# TODO: rewrite as a stand-alone Rust command-line tool.
|
|
|
|
# zebra-consensus accepts an ordered list of checkpoints, starting with the
|
|
# genesis block. Checkpoint heights can be chosen arbitrarily.
|
|
|
|
# We limit the memory usage for each checkpoint, based on the cumulative size of
|
|
# the serialized blocks in the chain. Deserialized blocks are larger, because
|
|
# they contain pointers and non-compact integers. But they should be within a
|
|
# constant factor of the serialized size.
|
|
MAX_CHECKPOINT_BYTE_COUNT=$((256*1024*1024))
|
|
|
|
# We limit the maximum number of blocks in each checkpoint. Each block uses a
|
|
# constant amount of memory for the supporting data structures and futures.
|
|
#
|
|
# TODO: In the Rust implementation, set this gap to half the sync service's
|
|
# LOOKAHEAD_LIMIT.
|
|
MAX_CHECKPOINT_HEIGHT_GAP=2000
|
|
|
|
cumulative_bytes=0
|
|
height_gap=0
|
|
while read -r height size hash; do
|
|
cumulative_bytes=$((cumulative_bytes + size))
|
|
height_gap=$((height_gap + 1))
|
|
|
|
# Checkpoints can be slightly larger the maximum byte count. That's ok,
|
|
# because the memory usage is only approximate. (This is a bash-specific
|
|
# optimisation, to avoid keeping a copy of the previous height and hash.
|
|
# Since exact sizes don't matter, we can use the same check in the Rust
|
|
# implementation. Or choose a simpler alternative.)
|
|
if [ "$height" -eq 0 ] || \
|
|
[ "$cumulative_bytes" -ge "$MAX_CHECKPOINT_BYTE_COUNT" ] || \
|
|
[ "$height_gap" -ge "$MAX_CHECKPOINT_HEIGHT_GAP" ]; then
|
|
|
|
# Reverse the byte order of hash.
|
|
#
|
|
# We reverse the hash after selecting the checkpoints, because launching
|
|
# a zebrad subprocess is expensive. (This is a bash-specific
|
|
# optimisation, the Rust implementation should reverse hashes as it loads
|
|
# them.)
|
|
hash=$(zebrad revhex "$hash")
|
|
|
|
echo "$height $hash"
|
|
|
|
cumulative_bytes=0
|
|
height_gap=0
|
|
fi
|
|
done
|