| 98 | |
| 99 | |
| 100 | def test(source, adjust): |
| 101 | # Variables to keep track of for stats purposes |
| 102 | ema = maxema = minema = TARGET |
| 103 | lthalf, gtdouble, lttq, gtft = 0, 0, 0, 0 |
| 104 | count = 0 |
| 105 | # Block times |
| 106 | times = [0] |
| 107 | # Block difficulty values |
| 108 | diffs = [source[0]] |
| 109 | # Next time to print status update |
| 110 | nextprint = 10**6 |
| 111 | # Main loop |
| 112 | while times[-1] < len(source) * SECONDS_IN_DAY: |
| 113 | # Print status update every 10**6 seconds |
| 114 | if times[-1] > nextprint: |
| 115 | print '%d out of %d processed, ema %f' % \ |
| 116 | (times[-1], len(source) * SECONDS_IN_DAY, ema) |
| 117 | nextprint += 10**6 |
| 118 | # Grab hashpower from data source |
| 119 | hashpower = source[int(times[-1] // SECONDS_IN_DAY)] |
| 120 | # Calculate new difficulty |
| 121 | diffs.append(adjust(times, diffs)) |
| 122 | # Calculate next block time |
| 123 | times.append(times[-1] + expdiff(diffs[-1] / hashpower)) |
| 124 | # Calculate min and max ema |
| 125 | ema = ema * (1 - EMA_FACTOR) + (times[-1] - times[-2]) * EMA_FACTOR |
| 126 | minema = min(minema, ema) |
| 127 | maxema = max(maxema, ema) |
| 128 | count += 1 |
| 129 | # Keep track of number of blocks we are below 75/50% or above |
| 130 | # 133/200% of target |
| 131 | if ema < TARGET * 0.75: |
| 132 | lttq += 1 |
| 133 | if ema < TARGET * 0.5: |
| 134 | lthalf += 1 |
| 135 | elif ema > TARGET * 1.33333: |
| 136 | gtft += 1 |
| 137 | if ema > TARGET * 2: |
| 138 | gtdouble += 1 |
| 139 | # Pop items to save memory |
| 140 | if len(times) > 2000: |
| 141 | times.pop(0) |
| 142 | diffs.pop(0) |
| 143 | print 'min', minema, 'max', maxema, 'avg', times[-1] / count, \ |
| 144 | 'ema < half', lthalf * 1.0 / count, \ |
| 145 | 'ema > double', gtdouble * 1.0 / count, \ |
| 146 | 'ema < 3/4', lttq * 1.0 / count, \ |
| 147 | 'ema > 4/3', gtft * 1.0 / count |
| 148 | |
| 149 | # Example usage |
| 150 | # blkdiff.test(blkdiff.hashpower, blkdiff.simple_adjust) |