forked from Qortal/qortal
CalDescent
3 years ago
11 changed files with 302 additions and 9 deletions
@ -0,0 +1,23 @@
|
||||
package org.qortal.api.model; |
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType; |
||||
import javax.xml.bind.annotation.XmlAccessorType; |
||||
import java.math.BigDecimal; |
||||
import java.math.BigInteger; |
||||
|
||||
@XmlAccessorType(XmlAccessType.FIELD) |
||||
public class BlockMintingInfo { |
||||
|
||||
public byte[] minterPublicKey; |
||||
public int minterLevel; |
||||
public int onlineAccountsCount; |
||||
public BigDecimal maxDistance; |
||||
public BigInteger keyDistance; |
||||
public double keyDistanceRatio; |
||||
public long timestamp; |
||||
public long timeDelta; |
||||
|
||||
public BlockMintingInfo() { |
||||
} |
||||
|
||||
} |
@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env bash |
||||
|
||||
start_height=$1 |
||||
count=$2 |
||||
target=$3 |
||||
deviation=$4 |
||||
power=$5 |
||||
|
||||
if [ -z "${start_height}" ]; then |
||||
echo |
||||
echo "Error: missing start height." |
||||
echo |
||||
echo "Usage:" |
||||
echo "block-timings.sh <startheight> [count] [target] [deviation] [power]" |
||||
echo |
||||
echo "startheight: a block height, preferably within the untrimmed range, to avoid data gaps" |
||||
echo "count: the number of blocks to request and analyse after the start height. Default: 100" |
||||
echo "target: the target block time in milliseconds. Originates from blockchain.json. Default: 60000" |
||||
echo "deviation: the allowed block time deviation in milliseconds. Originates from blockchain.json. Default: 30000" |
||||
echo "power: used when transforming key distance to a time offset. Originates from blockchain.json. Default: 0.2" |
||||
echo |
||||
exit |
||||
fi |
||||
|
||||
count=${count:=100} |
||||
target=${target:=60000} |
||||
deviation=${deviation:=30000} |
||||
power=${power:=0.2} |
||||
|
||||
finish_height=$((start_height + count - 1)) |
||||
height=$start_height |
||||
|
||||
echo "Settings:" |
||||
echo "Target time offset: ${target}" |
||||
echo "Deviation: ${deviation}" |
||||
echo "Power transform: ${power}" |
||||
echo |
||||
|
||||
function calculate_time_offset { |
||||
local key_distance_ratio=$1 |
||||
local transformed=$( echo "" | awk "END {print ${key_distance_ratio} ^ ${power}}") |
||||
local time_offset=$(echo "${deviation}*2*${transformed}" | bc) |
||||
time_offset=${time_offset%.*} |
||||
echo $time_offset |
||||
} |
||||
|
||||
|
||||
function fetch_and_process_blocks { |
||||
|
||||
echo "Fetching blocks from height ${start_height} to ${finish_height}..." |
||||
echo |
||||
|
||||
total_time_offset=0 |
||||
errors=0 |
||||
|
||||
while [ "${height}" -le "${finish_height}" ]; do |
||||
block_minting_info=$(curl -s "http://localhost:12391/blocks/byheight/${height}/mintinginfo") |
||||
error=$(echo "${block_minting_info}" | jq -r .error) |
||||
if [ "${error}" != "null" ]; then |
||||
echo "Error fetching minting info for block ${height}" |
||||
echo |
||||
errors=$((errors+1)) |
||||
height=$((height+1)) |
||||
continue; |
||||
fi |
||||
|
||||
# Parse minting info |
||||
minter_level=$(echo "${block_minting_info}" | jq -r .minterLevel) |
||||
online_accounts_count=$(echo "${block_minting_info}" | jq -r .onlineAccountsCount) |
||||
key_distance_ratio=$(echo "${block_minting_info}" | jq -r .keyDistanceRatio) |
||||
time_delta=$(echo "${block_minting_info}" | jq -r .timeDelta) |
||||
|
||||
time_offset=$(calculate_time_offset "${key_distance_ratio}") |
||||
block_time=$((target-deviation+time_offset)) |
||||
|
||||
echo "=== BLOCK ${height} ===" |
||||
echo "Minter level: ${minter_level}" |
||||
echo "Online accounts: ${online_accounts_count}" |
||||
echo "Key distance ratio: ${key_distance_ratio}" |
||||
echo "Time offset: ${time_offset}" |
||||
echo "Block time (real): ${time_delta}" |
||||
echo "Block time (calculated): ${block_time}" |
||||
|
||||
if [ "${time_delta}" -ne "${block_time}" ]; then |
||||
echo "WARNING: Block time mismatch. This is to be expected when using custom settings." |
||||
fi |
||||
echo |
||||
|
||||
total_time_offset=$((total_time_offset+block_time)) |
||||
|
||||
height=$((height+1)) |
||||
done |
||||
|
||||
adjusted_count=$((count-errors)) |
||||
if [ "${adjusted_count}" -eq 0 ]; then |
||||
echo "No blocks were retrieved." |
||||
echo |
||||
exit; |
||||
fi |
||||
|
||||
mean_time_offset=$((total_time_offset/adjusted_count)) |
||||
time_offset_diff=$((mean_time_offset-target)) |
||||
|
||||
echo "===================" |
||||
echo "===== SUMMARY =====" |
||||
echo "===================" |
||||
echo "Total blocks retrieved: ${adjusted_count}" |
||||
echo "Total blocks failed: ${errors}" |
||||
echo "Mean time offset: ${mean_time_offset}ms" |
||||
echo "Target time offset: ${target}ms" |
||||
echo "Difference from target: ${time_offset_diff}ms" |
||||
echo |
||||
|
||||
} |
||||
|
||||
function estimate_key_distance_ratio_for_level { |
||||
local level=$1 |
||||
local example_key_distance="0.5" |
||||
echo "(${example_key_distance}/${level})" |
||||
} |
||||
|
||||
function estimate_block_timestamps { |
||||
min_block_time=9999999 |
||||
max_block_time=0 |
||||
|
||||
echo "===== BLOCK TIME ESTIMATES =====" |
||||
|
||||
for level in {1..10}; do |
||||
example_key_distance_ratio=$(estimate_key_distance_ratio_for_level "${level}") |
||||
time_offset=$(calculate_time_offset "${example_key_distance_ratio}") |
||||
block_time=$((target-deviation+time_offset)) |
||||
|
||||
if [ "${block_time}" -gt "${max_block_time}" ]; then |
||||
max_block_time=${block_time} |
||||
fi |
||||
if [ "${block_time}" -lt "${min_block_time}" ]; then |
||||
min_block_time=${block_time} |
||||
fi |
||||
|
||||
echo "Level: ${level}, time offset: ${time_offset}, block time: ${block_time}" |
||||
done |
||||
block_time_range=$((max_block_time-min_block_time)) |
||||
echo "Range: ${block_time_range}" |
||||
echo |
||||
} |
||||
|
||||
fetch_and_process_blocks |
||||
estimate_block_timestamps |
Loading…
Reference in new issue