V40-V43: band umur vote (BARU/VALID/KADALUARSA, scan simpan semua umur) → REVOTE = VALID langsung (V42) → tag mint 1-hari + badge VOTE ULANG SEGERA (V43) ; klaim recovery jendela lewat + parse respons dict rows (B7/B8) ; backend mysql test_mariadb ; oracle test_dashboard/distribute/get_voters/mariadb ; images web/scan/dist/claim rebuild + push

This commit is contained in:
proitlab committed 2026-08-07 12:07:34 +07:00
1 parent af9a0291b9
commit 81ec6bdfe7
17 files changed
+914 -148

No files matched your search

+31 -13
View File
@@ -2,8 +2,9 @@
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.
Pemilih buatan memakai bobot segar (revote ~sekarang); sejak V40 baris basi
JUGA disimpan (banding/tampil/bayar menghitung umur saat query) — contoh basi
membuktikan ia lolos ke snapshot, bukan dibuang.
"""
import os
@@ -105,7 +106,8 @@ def main():
norm = [n for n in norm if n is not None]
norm_owners = [n['owner'] for n in norm]
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))
check('V5 hanya BP target', all(n['owner'] in ('aaa1', 'ccc3', 'zzz9')
for n in norm))
by = {n['owner']: n for n in norm}
aaa1_w = _fresh_weight(12000000)
check('V6 bobot verbatim TEXT', by['aaa1']['weight'] == aaa1_w)
@@ -114,13 +116,15 @@ def main():
check('staked ÷10000', by['aaa1']['staked'] == 1200.0)
check('staked batas ≥1000 ÷10000', by['ccc3']['staked'] == 1000.0)
# V13: last_vote diturunkan di normalize; baris basi dibuang (⊥ disimpan)
# V13: last_vote diturunkan di normalize; V40: basi tetap disimpan
check('V13 last_vote ikut dinormalisasi', 'last_vote' in by['aaa1'])
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))
>= datetime.now() - timedelta(days=28))
check('V40 basi (zzz9) tetap disimpan', by['zzz9']['owner'] == 'zzz9')
check('V40 last_vote basi zzz9 ~900 hari lalu',
(datetime.now() - datetime.fromisoformat(by['zzz9']['last_vote'])).days
> 800)
# 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)
@@ -134,12 +138,12 @@ 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],
# V13/V40: normalize menyimpan basi, membuang yang tak dapat diverifikasi
old = gv.normalize({'owner': 'old8', 'producers': [gv.TARGET_BP],
'staked': 20000000,
'last_vote_weight': _fresh_weight(20000000, days_ago=900)})
is None)
check('V40 normalize basi (900 hari) → disimpan',
old is not None and old['owner'] == 'old8')
check('V13 normalize bobot kosong (unverifiable) → None',
gv.normalize({'owner': 'unk7', 'producers': [gv.TARGET_BP],
'staked': 20000000, 'last_vote_weight': ''}) is None)
@@ -180,7 +184,7 @@ def main():
{'owner': 'aaa1', 'weight': '111.0', 'staked': 1200.0},
{'owner': 'ccc3', 'weight': '222.0', 'staked': 1000.0},
]
gv.persist(set_a)
scanned_a = gv.persist(set_a)
conn = sqlite3.connect(db.DB_PATH)
cnt = conn.execute('SELECT COUNT(*) FROM voters').fetchone()[0]
conn.close()
@@ -190,7 +194,7 @@ def main():
{'owner': 'aaa1', 'weight': '999.0', 'staked': 5000.0},
{'owner': 'ddd4', 'weight': '333.0', 'staked': 2000.0},
]
gv.persist(set_b)
scanned_b = gv.persist(set_b)
conn = sqlite3.connect(db.DB_PATH)
rows = conn.execute('SELECT owner, weight, staked, scanned_at FROM voters').fetchall()
by = {r[0]: r for r in rows}
@@ -206,6 +210,20 @@ def main():
check('V7 owner PRIMARY KEY', 'owner' in cols and pk == ['owner'])
check('V7 kolom last_vote ada', 'last_vote' in cols)
# V41: first_seen — kemunculan pertama tiap owner, idempoten (⊥ overwrite)
db.record_first_seen([{'owner': 'aaa1'}], '2000-01-01T00:00:00')
conn = sqlite3.connect(db.DB_PATH)
fs = {r[0]: r[1] for r in conn.execute(
'SELECT owner, first_seen_at FROM voter_first_seen').fetchall()}
conn.close()
check('V41 first_seen tercatat utk semua owner',
set(fs) == {'aaa1', 'ccc3', 'ddd4'})
check('V41 first_seen = kemunculan pertama',
fs['aaa1'] == scanned_a and fs['ccc3'] == scanned_a
and fs['ddd4'] == scanned_b)
check('V41 first_seen idempoten (record ulang ⊥ overwrite)',
fs['aaa1'] == scanned_a and fs['aaa1'] != '2000-01-01T00:00:00')
print('\nSEMUA UJI PASS')