public void BootstrapVoting(Protocol protocol, List <Account> accounts) { var snapshots = accounts .Where(x => x.Type == AccountType.Delegate) .Select(x => x as Delegate) .Select(x => new VotingSnapshot { Level = 1, Period = 0, BakerId = x.Id, Rolls = (int)(x.StakingBalance / protocol.TokensPerRoll), Status = VoterStatus.None }); var period = new VotingPeriod { Index = 0, Epoch = 0, FirstLevel = 1, LastLevel = protocol.BlocksPerVoting, Kind = PeriodKind.Proposal, Status = PeriodStatus.Active, TotalBakers = snapshots.Count(), TotalRolls = snapshots.Sum(x => x.Rolls), UpvotesQuorum = protocol.ProposalQuorum, ProposalsCount = 0, TopUpvotes = 0, TopRolls = 0 }; Db.VotingSnapshots.AddRange(snapshots); Db.VotingPeriods.Add(period); Cache.Periods.Add(period); }
protected PeriodStatus GetPeriodStatus(VotingPeriod p) { if (p.Kind == PeriodKind.Proposal) { if (p.ProposalsCount == 0) { return(PeriodStatus.NoProposals); } if (p.TopRolls < p.TotalRolls * p.UpvotesQuorum / 10000) { return(PeriodStatus.NoQuorum); } } else if (p.Kind == PeriodKind.Exploration || p.Kind == PeriodKind.Promotion) { if (p.YayRolls + p.NayRolls + p.PassRolls < p.TotalRolls * p.BallotsQuorum / 10000) { return(PeriodStatus.NoQuorum); } if (p.YayRolls < (p.YayRolls + p.NayRolls) * p.Supermajority / 10000) { return(PeriodStatus.NoSupermajority); } } return(PeriodStatus.Success); }
void FillBallots(StringBuilder post, VotingPeriod vp) { post.AppendLine("<ul>"); post.AppendLine($"<li>Yay - {vp.yayRolls} rolls ({(100D * vp.yayRolls / (vp.yayRolls + vp.nayRolls + vp.passRolls)) ?? 0:##0.0}%)</li>"); post.AppendLine($"<li>Nay - {vp.nayRolls} rolls ({(100D * vp.nayRolls / (vp.yayRolls + vp.nayRolls + vp.passRolls)) ?? 0:##0.0}%)</li>"); post.AppendLine($"<li>Pass - {vp.passRolls} rolls ({(100D * vp.passRolls / (vp.yayRolls + vp.nayRolls + vp.passRolls)) ?? 0:##0.0}%)</li>"); post.AppendLine("</ul>"); }
protected virtual VotingPeriod StartNextPeriod(Block block, VotingPeriod current) { return(current.Kind switch { PeriodKind.Proposal => StartBallotPeriod(block, current, PeriodKind.Exploration), PeriodKind.Exploration => StartWaitingPeriod(block, current, PeriodKind.Testing), PeriodKind.Testing => StartBallotPeriod(block, current, PeriodKind.Promotion), PeriodKind.Promotion => StartProposalPeriod(block, current), _ => throw new Exception("Invalid voting period kind") });
void BallotQuorum(StringBuilder post, VotingPeriod vp) { if (vp.ballotsQuorum < (100M * (vp.yayRolls + vp.nayRolls + vp.passRolls) / vp.totalRolls)) { post.AppendLine($"<p>Quorum of {vp.ballotsQuorum:#0.0}% reached</p>"); } else { post.AppendLine($"<p>Quorum of {vp.ballotsQuorum:#0.0}% not reached</p>"); } }
public async Task Init(RawBlock rawBlock) { var protocol = await Cache.Protocols.GetAsync(rawBlock.Protocol); VotingPeriod = new ProposalPeriod { Code = 0, Epoch = new VotingEpoch { Level = rawBlock.Level }, Kind = VotingPeriods.Proposal, StartLevel = rawBlock.Level, EndLevel = protocol.BlocksPerVoting }; }
protected override int GetParticipationEma(VotingPeriod period, Protocol proto) { var prev = Db.VotingPeriods .AsNoTracking() .OrderByDescending(x => x.Index) .FirstOrDefault(x => x.Kind == PeriodKind.Exploration || x.Kind == PeriodKind.Promotion); if (prev != null) { var participation = 10000 * (prev.YayRolls + prev.NayRolls + prev.PassRolls) / prev.TotalRolls; return(((int)prev.ParticipationEma * 8000 + (int)participation * 2000) / 10000); } return(proto.BallotQuorumMax); }
protected virtual ProposalStatus GetProposalStatus(Proposal proposal, VotingPeriod period) { if (period.Status == PeriodStatus.Success) { return(period.Kind == PeriodKind.Promotion ? ProposalStatus.Accepted : ProposalStatus.Active); } if (period.Status == PeriodStatus.NoSupermajority) { return(ProposalStatus.Rejected); } return(ProposalStatus.Skipped); }
protected async Task UpdateProposalsStatus(VotingPeriod p) { if (p.Kind == PeriodKind.Proposal) { if (p.Status == PeriodStatus.NoProposals) { return; } var proposals = await Db.Proposals .Where(x => x.Status == ProposalStatus.Active) .ToListAsync(); foreach (var proposal in proposals) { proposal.Status = ProposalStatus.Skipped; } if (p.Status == PeriodStatus.Success) { var winner = proposals.First(x => x.Rolls == p.TopRolls); winner.Status = GetProposalStatus(winner, p); if (winner.Status == ProposalStatus.Active) { winner.LastPeriod = p.Index + 1; } } } else { var proposal = await Db.Proposals.FirstAsync(x => x.Status == ProposalStatus.Active); proposal.Status = GetProposalStatus(proposal, p); if (proposal.Status == ProposalStatus.Active) { proposal.LastPeriod = p.Index + 1; } } }
public void Remove() { VotingPeriod = null; }
public void Add(VotingPeriod period) { VotingPeriod = period; }
public void Reset() { VotingPeriod = null; }
public async Task Init(Block block) { VotingPeriod = await Db.VotingPeriods.Include(x => x.Epoch).SingleAsync(); }
protected override int GetBallotQuorum(VotingPeriod period, Protocol proto) { return(proto.BallotQuorumMin + (int)period.ParticipationEma * (proto.BallotQuorumMax - proto.BallotQuorumMin) / 10000); }
public void Remove(VotingPeriod period) { Cached.Remove(period.Index); }
public void Add(VotingPeriod period) { CheckSpace(); Cached[period.Index] = period; }