T15: buang voter basi di scan + hapus bobot suara & UI basi di web
get_voters.py kini menyimpan hanya pemilih segar (last_vote tak diketahui atau > VEX_STALE_DAYS dibuang di normalize, V13). Web menampilkan kolom RANK/AKUN/STAKE/VOTE TERAKHIR, tanpa BOBOT SUARA, stat VOTE BASI, penanda/ filter ?stale=1 (V15). voters.db dipangkas 336 → 42. Oracle diperbarui dan lolos.
This commit is contained in:
1 parent
b0b3ba8ab3
commit
41990af9af
10 files changed
+131
-159
No files matched your search
+47
-15
@@ -2,18 +2,26 @@
|
||||
|
||||
Oracle: `./venv/bin/python test_get_voters.py` harus exit 0.
|
||||
Dalam setiap contoh, 'last_vote_weight' berisi 17 desimal (bobot teliti).
|
||||
Pemilih buatan memakai bobot segar (revote ~sekarang) supaya lolos saringan
|
||||
V13; baris basi ditambahkan eksplisit untuk membuktikan ia dibuang.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sqlite3
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import requests
|
||||
|
||||
import get_voters as gv
|
||||
|
||||
|
||||
def _fresh_weight(staked_raw, days_ago=5):
|
||||
"""Bobot untuk revote ~sekarang: staked_raw × 2^(tahun sejak 2000)."""
|
||||
t = ((datetime.now() - gv.WEIGHT_EPOCH).days - days_ago) / 365.25
|
||||
return f'{staked_raw * 2 ** t:.17f}'
|
||||
|
||||
|
||||
class FakePayload:
|
||||
passes = 0
|
||||
|
||||
@@ -26,21 +34,26 @@ class FakePayload:
|
||||
'staked': 10000, 'last_vote_weight': '0.00'},
|
||||
{'owner': 'aaa1', 'producers': [gv.TARGET_BP],
|
||||
'staked': 12000000,
|
||||
'last_vote_weight': '12345.678901234567890'},
|
||||
'last_vote_weight': _fresh_weight(12000000)},
|
||||
{'owner': 'bbb2', 'producers': ['wind'],
|
||||
'staked': 9000, 'last_vote_weight': '999.0'},
|
||||
], 'more': True},
|
||||
'bbb2': {'rows': [
|
||||
{'owner': 'aaa1', 'producers': [gv.TARGET_BP],
|
||||
'staked': 12000000,
|
||||
'last_vote_weight': '12345.678901234567890'},
|
||||
'last_vote_weight': _fresh_weight(12000000)},
|
||||
{'owner': 'ccc3', 'producers': [gv.TARGET_BP],
|
||||
'staked': 10000000, 'last_vote_weight': '0.50000000000000000'},
|
||||
], 'more': True},
|
||||
'staked': 10000000,
|
||||
'last_vote_weight': _fresh_weight(10000000)},
|
||||
], 'more': True},
|
||||
'ccc3': {'rows': [
|
||||
{'owner': 'ccc3', 'producers': [gv.TARGET_BP],
|
||||
'staked': 10000000, 'last_vote_weight': '0.50000000000000000'},
|
||||
], 'more': False},
|
||||
'staked': 10000000,
|
||||
'last_vote_weight': _fresh_weight(10000000)},
|
||||
{'owner': 'zzz9', 'producers': [gv.TARGET_BP],
|
||||
'staked': 15000000,
|
||||
'last_vote_weight': _fresh_weight(15000000, days_ago=900)},
|
||||
], 'more': False},
|
||||
}
|
||||
FakePayload.passes += 1
|
||||
if FakePayload.passes > 20:
|
||||
@@ -84,7 +97,7 @@ def main():
|
||||
raw = gv.scan_voters()
|
||||
owners = [r['owner'] for r in raw]
|
||||
check('V2/V3 pembuangan duplikat',
|
||||
owners == [gv.ZERO_OWNER, 'aaa1', 'bbb2', 'ccc3'])
|
||||
owners == [gv.ZERO_OWNER, 'aaa1', 'bbb2', 'ccc3', 'zzz9'])
|
||||
|
||||
# V4 + V5 + V6: saringan sentinel & BP target terjadi di normalize
|
||||
norm = [gv.normalize(r) for r in raw]
|
||||
@@ -93,17 +106,20 @@ def main():
|
||||
check('V4 sentinel "0" dilewati', gv.ZERO_OWNER not in norm_owners)
|
||||
check('V5 hanya BP target', all(n['owner'] in ('aaa1', 'ccc3') for n in norm))
|
||||
by = {n['owner']: n for n in norm}
|
||||
check('V6 bobot verbatim TEXT', by['aaa1']['weight'] == '12345.678901234567890')
|
||||
aaa1_w = _fresh_weight(12000000)
|
||||
check('V6 bobot verbatim TEXT', by['aaa1']['weight'] == aaa1_w)
|
||||
check('V6 bobot bukan float-rounded',
|
||||
by['aaa1']['weight'] != str(float(by['aaa1']['weight'])))
|
||||
check('staked ÷10000', by['aaa1']['staked'] == 1200.0)
|
||||
check('staked batas ≥1000 ÷10000', by['ccc3']['staked'] == 1000.0)
|
||||
|
||||
# V13: last_vote diturunkan di normalize dari rasio bobot/stake
|
||||
# V13: last_vote diturunkan di normalize; baris basi dibuang (⊥ disimpan)
|
||||
check('V13 last_vote ikut dinormalisasi', 'last_vote' in by['aaa1'])
|
||||
check('V13 bobot/stake rasio kecil → sebelum 2000',
|
||||
by['ccc3']['last_vote'] is not None
|
||||
and by['ccc3']['last_vote'] < '2000-01-01')
|
||||
check('V13 last_vote segar (≤ VEX_STALE_DAYS)',
|
||||
datetime.fromisoformat(by['aaa1']['last_vote'])
|
||||
>= datetime.now() - timedelta(days=gv.VEX_STALE_DAYS))
|
||||
check('V13 basi (zzz9) dibuang di normalize',
|
||||
all(n['owner'] != 'zzz9' for n in norm))
|
||||
|
||||
# V13: formula — staked_raw × 2^26 → ~2026-01-01 (±2 hari, toleransi 365.25 hari/tahun)
|
||||
lv = gv.derive_last_vote(f'{12000000 * 2 ** 26}.00000000000000000', 1200.0)
|
||||
@@ -117,17 +133,33 @@ def main():
|
||||
check('V13 bobot tak valid → None', gv.derive_last_vote('abc', 1200.0) is None)
|
||||
check('V13 stake nol → None', gv.derive_last_vote('1.0', 0.0) is None)
|
||||
|
||||
# V13: normalize membuang basi / tak dapat diverifikasi, menyimpan segar
|
||||
check('V13 normalize basi → None',
|
||||
gv.normalize({'owner': 'old8', 'producers': [gv.TARGET_BP],
|
||||
'staked': 20000000,
|
||||
'last_vote_weight': _fresh_weight(20000000, days_ago=900)})
|
||||
is None)
|
||||
check('V13 normalize bobot kosong (unverifiable) → None',
|
||||
gv.normalize({'owner': 'unk7', 'producers': [gv.TARGET_BP],
|
||||
'staked': 20000000, 'last_vote_weight': ''}) is None)
|
||||
check('V13 normalize segar → disimpan',
|
||||
gv.normalize({'owner': 'new6', 'producers': [gv.TARGET_BP],
|
||||
'staked': 20000000,
|
||||
'last_vote_weight': _fresh_weight(20000000)})['owner'] == 'new6')
|
||||
|
||||
# V9: staked < 1000 VEX → dibuang; tepat 1000 → disimpan
|
||||
check('V9 di bawah 1000 dibuang',
|
||||
gv.normalize({'owner': 'low9', 'producers': [gv.TARGET_BP],
|
||||
'staked': 9999999, 'last_vote_weight': '1.0'}) is None)
|
||||
check('V9 tepat 1000 disimpan',
|
||||
gv.normalize({'owner': 'eq10', 'producers': [gv.TARGET_BP],
|
||||
'staked': 10000000, 'last_vote_weight': '1.0'})['staked'] == 1000.0)
|
||||
'staked': 10000000,
|
||||
'last_vote_weight': _fresh_weight(10000000)})['staked'] == 1000.0)
|
||||
|
||||
# V8: node kadang memberi staked sebagai string → tetap dinormalisasi
|
||||
srow = {'owner': 'eee5', 'producers': [gv.TARGET_BP],
|
||||
'staked': '10000010000', 'last_vote_weight': '42.0'}
|
||||
'staked': '10000010000',
|
||||
'last_vote_weight': _fresh_weight(10000010000)}
|
||||
snorm = gv.normalize(srow)
|
||||
check('V8 staked string → float ÷10000', snorm['staked'] == 1000001.0)
|
||||
|
||||
|
||||
Reference in new issue
Block a user