Phase 2: mixer (Web3 tab in the network, terminal page, sanctions, night return), unlock registration per upgrade

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ZHU MINCHAOandClaude Sonnet 5.5 committed 2026-11-03 16:39:40 +08:00
1 parent 133367b58d
commit 09a5cae69c
11 files changed
+290 -16

No files matched your search

@@ -498,6 +498,34 @@ internal static class Program
Check(CoinPayment.Receive(w, Assets.CRC, 0, 1, 10) == 0, "零金额不收");
});
Test("混币器:按价值比例带走污点、轮数即天数、手续费与清洗、匿名集、制裁标记", () =>
{
Func<string, double> px = a => a == Assets.PSC ? 10 : 1;
var w = new Wallet { Address = "t" };
w.Add(Assets.CRC, 1000); w.Add(Assets.PSC, 100); // 总价值 2000
w.Taint = 400; w.Basis = 1000;
var m = new Mixer();
Check(m.Deposit(w, Assets.CRC, 1000, 9, 1, px) == null && m.Deposit(w, Assets.CRC, 50, 1, 1, px) == null, "轮数超限、低于最小额不收");
var d = m.Deposit(w, Assets.CRC, 1000, 2, 1, px);
Check(d != null && Near(d.Taint, 200, 1e-9) && Near(w.Taint, 200, 1e-9) && Near(w.Get(Assets.CRC), 0, 1e-9), "存入 1000 / 2000:带走一半污点");
var rng = new Rng(3);
Check(m.Night(w, 2, px, rng).Count == 0, "未到期不提回");
var res = m.Night(w, 3, px, rng);
Check(res.Count == 1 && !res[0].Rugged, "到期提回");
double rate = Mixer.RoundRate(1000);
Check(Near(w.Get(Assets.CRC), 1000 * 0.98 * 0.98, 1e-6) && Near(res[0].TaintAfter, 200 * (1 - rate) * (1 - rate), 1e-6), "两轮:手续费与污点按轮数递减");
Check(Mixer.RoundRate(100000) < Mixer.RoundRate(1000) / 3, "存入越大匿名集占比越大,清洗越差");
Check(m.RecentlyMixed(3) && !m.RecentlyMixed(3 + Tuning.AmlWindowDays + 1), "提回后一段时间内出金按混币来源加重");
m.OnEvent(MarketEvent.Crackdown, 5, new Rng(1));
int hit = 0; for (int i = 0; i < 400; i++) { var t = new Mixer(); t.OnEvent(MarketEvent.Crackdown, 1, new Rng((ulong)i + 1)); if (t.Sanctioned(2)) hit++; }
Check(hit > 150 && hit < 250, $"镇压时约一半概率被制裁:{hit}/400");
var w2 = new Wallet { Address = "u" }; w2.Add(Assets.CRC, 500);
var m2 = new Mixer { SanctionedUntil = 10 };
m2.Deposit(w2, Assets.CRC, 500, 1, 1, px);
m2.Night(w2, 2, px, new Rng(5));
Check(w2.Flagged, "制裁期间提出的币被标记");
});
Console.WriteLine($"\n{_passed} 通过,{_failed} 失败");
return _failed == 0 ? 0 : 1;
}