Estate-rule sim: pin the stake arm to heimdall-stake golden vectors #6
3 changed files with 64 additions and 0 deletions
|
|
@ -473,6 +473,10 @@ def stake_params(name, overrides=()):
|
|||
def log_weight(x, b, unit):
|
||||
"""w = 1 + log_b(x/unit): 1 at x = unit, 0 (not negative) below unit.
|
||||
|
||||
Equals CultLib heimdall-stake `weight` with floor 0, cap None and min_amount_per_identity = unit, which
|
||||
is the cliff at unit; Libby's continuous log below unit is not used. Pinned to her golden vectors by
|
||||
test_estatesim.StakeVectors (vectors/stake_golden.csv).
|
||||
|
||||
This is the weight of ONE IDENTITY. It is not sybil-safe: log is sub-linear, so the same x split over
|
||||
k identities weighs more (split_weight). Whether the log bounds a purchase depends on identities being
|
||||
scarce, which nothing in this module supplies. b and unit are PLACEHOLDER values (STAKE_BASE)."""
|
||||
|
|
|
|||
|
|
@ -506,5 +506,36 @@ class HarnessTests(unittest.TestCase):
|
|||
self.assertEqual(E.verdict((-.01, .05), (0.0, .02)), "undecided")
|
||||
|
||||
|
||||
|
||||
class StakeVectors(unittest.TestCase):
|
||||
"""Pins the arm's log_weight / split_weight to CultLib heimdall-stake's golden vectors (PR #9, head 84f932ec,
|
||||
copied unmodified to vectors/stake_golden.csv). The arm is Libby's function with min_amount_per_identity = unit,
|
||||
so rows at or above the unit must match; a row below the unit must be 0 in the arm (the cliff) while the
|
||||
vectors, which set no minimum, give the continuous value. Vectors are integer cents and micro-weights, the
|
||||
arm is float and unit-agnostic: tolerance is 1 micro-weight per identity (Libby rounds each identity, the arm the total)."""
|
||||
|
||||
@staticmethod
|
||||
def rows():
|
||||
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "vectors", "stake_golden.csv")
|
||||
with open(path) as fh:
|
||||
lines = [l.strip() for l in fh if l.strip() and not l.startswith("#")]
|
||||
out = [l.split(",") for l in lines]
|
||||
assert len(out) == 26
|
||||
return [(k, int(b), int(u), int(a), int(n), int(e)) for k, b, u, a, n, e in out]
|
||||
|
||||
def test_every_vector_row(self):
|
||||
for kind, b, u, a, k, expected in self.rows():
|
||||
with self.subTest(kind=kind, b=b, unit=u, amount=a, k=k):
|
||||
if kind == "single":
|
||||
got = E.log_weight(a, b, u) * 1e6
|
||||
if a < u:
|
||||
self.assertEqual(got, 0.0) # arm's cliff = min_amount_per_identity = unit
|
||||
continue
|
||||
else:
|
||||
got = E.split_weight(a, k, b, u)[0] * 1e6
|
||||
self.assertGreaterEqual(a // k, u) # every split row keeps each identity at or above unit
|
||||
self.assertLessEqual(abs(got - expected), max(1, k))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# kind,base,unit_cents,amount_cents,k,expected_micro
|
||||
# single: weight of one identity holding amount. split: budget (amount) split evenly over k identities (first amount%k hold one extra cent), summed.
|
||||
# expected values computed independently with 60-digit decimal ln, rounded half up. No floor, cap or minimum.
|
||||
single,10,100,100,1,1000000
|
||||
single,10,100,1000,1,2000000
|
||||
single,10,100,10000,1,3000000
|
||||
single,10,100,1000000,1,5000000
|
||||
single,10,100,50,1,698970
|
||||
single,10,100,10,1,0
|
||||
single,10,100,1,1,0
|
||||
single,2,100,400,1,3000000
|
||||
single,2,100,100,1,1000000
|
||||
single,2,1,1,1,1000000
|
||||
single,3,500,123456,1,6014537
|
||||
single,7,1,987654321,1,11643268
|
||||
single,10,1,1,1,1000000
|
||||
single,16,250,99999,1,3160960
|
||||
split,10,100,10000,1,3000000
|
||||
split,10,100,10000,2,5397940
|
||||
split,10,100,10000,10,20000000
|
||||
split,10,100,10000,100,100000000
|
||||
split,2,100,10000,1,7643856
|
||||
split,2,100,10000,2,13287712
|
||||
split,2,100,10000,10,43219280
|
||||
split,2,100,10000,100,100000000
|
||||
split,10,100,100000,1,4000000
|
||||
split,10,100,100000,2,7397940
|
||||
split,10,100,100000,10,30000000
|
||||
split,10,100,100000,100,200000000
|
||||
|
Loading…
Reference in a new issue