Many comments
This commit is contained in:
parent
5549c48500
commit
de2c4bffa3
|
@ -2,98 +2,124 @@ import math, random
|
|||
|
||||
hashpower = [float(x) for x in open('hashpower.csv').readlines()]
|
||||
|
||||
target = 12
|
||||
seconds_in_day = 86400
|
||||
ema_factor = 0.01
|
||||
f = 20
|
||||
sqrf = 3
|
||||
threshold = 1.3
|
||||
adj_factor = 0.01
|
||||
maxadjust = 0.5
|
||||
blks_back = 10
|
||||
# Target block time
|
||||
TARGET = 12
|
||||
# Should be 86400, but can reduce for a quicker sim
|
||||
SECONDS_IN_DAY = 86400
|
||||
# Look at the 1/x day exponential moving average
|
||||
EMA_FACTOR = 0.01
|
||||
# Damping factor for simple difficulty adjustment
|
||||
SIMPLE_ADJUST_DAMPING_FACTOR = 20
|
||||
# Maximum per-block diff adjustment (as fraction of current diff)
|
||||
SIMPLE_ADJUST_MAX = 0.5
|
||||
# Damping factor for quadratic difficulty adjustment
|
||||
QUADRATIC_ADJUST_DAMPING_FACTOR = 3
|
||||
# Maximum per-block diff adjustment (as fraction of current diff)
|
||||
QUADRATIC_ADJUST_MAX = 0.5
|
||||
# Threshold for bounded adjustor
|
||||
BOUNDED_ADJUST_THRESHOLD = 1.3
|
||||
# Bounded adjustment factor
|
||||
BOUNDED_ADJUST_FACTOR = 0.01
|
||||
# How many blocks back to look
|
||||
BLKS_BACK = 10
|
||||
|
||||
|
||||
# Produces a value according to the exponential distribution; used
|
||||
# to determine the time until the next block given an average block
|
||||
# time of t
|
||||
def expdiff(t):
|
||||
return -math.log(random.random()) * t
|
||||
|
||||
|
||||
def calc_threshold_time(p, t):
|
||||
return t * -math.log(1 - p)
|
||||
|
||||
|
||||
# abs_sqr(3) = 9, abs_sqr(-7) = -49, etc
|
||||
def abs_sqr(x):
|
||||
return -(x**2) if x < 0 else x**2
|
||||
|
||||
|
||||
# Given an array of the most recent timestamps, and the most recent
|
||||
# difficulties, compute the next difficulty
|
||||
def simple_adjust(timestamps, diffs):
|
||||
if len(timestamps) < blks_back + 2:
|
||||
if len(timestamps) < BLKS_BACK + 2:
|
||||
return diffs[-1]
|
||||
# Total interval between previous block and block a bit further back
|
||||
delta = timestamps[-2] - timestamps[-2-blks_back] + 0.0
|
||||
delta = timestamps[-2] - timestamps[-2-BLKS_BACK] + 0.0
|
||||
# Expected interval
|
||||
expected = target * blks_back
|
||||
fac = max(min(1 - (delta / expected - 1) / f, 1+maxadjust), 1-maxadjust)
|
||||
expected = TARGET * BLKS_BACK
|
||||
# Compute adjustment factor
|
||||
fac = 1 - (delta / expected - 1) / SIMPLE_ADJUST_DAMPING_FACTOR
|
||||
fac = max(min(fac, 1 + SIMPLE_ADJUST_MAX), 1 - SIMPLE_ADJUST_MAX)
|
||||
return diffs[-1] * fac
|
||||
|
||||
|
||||
# Alternative adjustment algorithm
|
||||
def quadratic_adjust(timestamps, diffs):
|
||||
if len(timestamps) < blks_back + 2:
|
||||
if len(timestamps) < BLKS_BACK + 2:
|
||||
return diffs[-1]
|
||||
# Total interval between previous block and block a bit further back
|
||||
delta = timestamps[-2] - timestamps[-2-blks_back] + 0.0
|
||||
delta = timestamps[-2] - timestamps[-2-BLKS_BACK] + 0.0
|
||||
# Expected interval
|
||||
expected = target * blks_back
|
||||
fac = max(min(1 - abs_sqr(delta / expected - 1) / sqrf,
|
||||
1+maxadjust), 1-maxadjust)
|
||||
expected = TARGET * BLKS_BACK
|
||||
# Compute adjustment factor
|
||||
fac = 1 - abs_sqr(delta / expected - 1) / QUADRATIC_ADJUST_DAMPING_FACTOR
|
||||
fac = max(min(fac, 1 + QUADRATIC_ADJUST_MAX), 1 - QUADRATIC_ADJUST_MAX)
|
||||
return diffs[-1] * fac
|
||||
|
||||
|
||||
# Alternative adjustment algorithm
|
||||
def bounded_adjust(timestamps, diffs):
|
||||
if len(timestamps) < blks_back + 2:
|
||||
if len(timestamps) < BLKS_BACK + 2:
|
||||
return diffs[-1]
|
||||
# Total interval between previous block and block a bit further back
|
||||
delta = timestamps[-2] - timestamps[-2-blks_back] + 0.0
|
||||
delta = timestamps[-2] - timestamps[-2-BLKS_BACK] + 0.0
|
||||
# Expected interval
|
||||
expected = target * blks_back
|
||||
if delta / expected > threshold:
|
||||
fac = (1 - adj_factor)
|
||||
elif delta / expected < 1 / threshold:
|
||||
fac = (1 + adj_factor) ** (delta / expected)
|
||||
expected = TARGET * BLKS_BACK
|
||||
if delta / expected > BOUNDED_ADJUST_THRESHOLD:
|
||||
fac = (1 - BOUNDED_ADJUST_FACTOR)
|
||||
elif delta / expected < 1 / BOUNDED_ADJUST_THRESHOLD:
|
||||
fac = (1 + BOUNDED_ADJUST_FACTOR) ** (delta / expected)
|
||||
else:
|
||||
fac = 1
|
||||
return diffs[-1] * fac
|
||||
|
||||
|
||||
def test(source, adjust):
|
||||
ema = maxema = minema = target
|
||||
# Variables to keep track of for stats purposes
|
||||
ema = maxema = minema = TARGET
|
||||
lthalf, gtdouble, lttq, gtft = 0, 0, 0, 0
|
||||
times = [0]
|
||||
diffs = [source[0]]
|
||||
nextprint = 10**6
|
||||
count = 0
|
||||
while times[-1] < len(source) * seconds_in_day:
|
||||
# Block times
|
||||
times = [0]
|
||||
# Block difficulty values
|
||||
diffs = [source[0]]
|
||||
# Next time to print status update
|
||||
nextprint = 10**6
|
||||
# Main loop
|
||||
while times[-1] < len(source) * SECONDS_IN_DAY:
|
||||
# Print status update every 10**6 seconds
|
||||
if times[-1] > nextprint:
|
||||
print '%d out of %d processed' % \
|
||||
(times[-1], len(source) * seconds_in_day)
|
||||
print '%d out of %d processed, ema %f' % \
|
||||
(times[-1], len(source) * SECONDS_IN_DAY, ema)
|
||||
nextprint += 10**6
|
||||
# Grab hashpower from data source
|
||||
hashpower = source[int(times[-1] // seconds_in_day)]
|
||||
hashpower = source[int(times[-1] // SECONDS_IN_DAY)]
|
||||
# Calculate new difficulty
|
||||
diffs.append(adjust(times, diffs))
|
||||
# Calculate next block time
|
||||
times.append(times[-1] + expdiff(diffs[-1] / hashpower))
|
||||
# Calculate min and max ema
|
||||
ema = ema * (1 - ema_factor) + (times[-1] - times[-2]) * ema_factor
|
||||
ema = ema * (1 - EMA_FACTOR) + (times[-1] - times[-2]) * EMA_FACTOR
|
||||
minema = min(minema, ema)
|
||||
maxema = max(maxema, ema)
|
||||
count += 1
|
||||
if ema < target * 0.75:
|
||||
# Keep track of number of blocks we are below 75/50% or above
|
||||
# 133/200% of target
|
||||
if ema < TARGET * 0.75:
|
||||
lttq += 1
|
||||
if ema < target * 0.5:
|
||||
if ema < TARGET * 0.5:
|
||||
lthalf += 1
|
||||
elif ema > target * 1.33333:
|
||||
elif ema > TARGET * 1.33333:
|
||||
gtft += 1
|
||||
if ema > target * 2:
|
||||
if ema > TARGET * 2:
|
||||
gtdouble += 1
|
||||
# Pop items to save memory
|
||||
if len(times) > 2000:
|
||||
|
@ -104,3 +130,6 @@ def test(source, adjust):
|
|||
'ema > double', gtdouble * 1.0 / count, \
|
||||
'ema < 3/4', lttq * 1.0 / count, \
|
||||
'ema > 4/3', gtft * 1.0 / count
|
||||
|
||||
# Example usage
|
||||
# blkdiff.test(blkdiff.hashpower, blkdiff.simple_adjust)
|
||||
|
|
Loading…
Reference in New Issue