Replace confirmation_solicitor with vote_solicitor (#5265) * Return representatives from the rep crawler as a deque Channel and batch listings across the node come back as deques, the rep crawler was the one list still returned as a vector, and the type spread into every consumer of its representatives. The confirmation solicitor takes the deque as it is. * Replace confirmation_solicitor with vote_solicitor Split solicitation into a pure per-round planner and a node component. vote_solicitor_round decides, election by election, which principal representatives get a confirm_req and which get the winner block, with the same rules and caps as before: a rep that voted for a different hash is exempt from the per election caps, after quorum only a final vote settles a rep, and a rep behind a full channel is left alone for the rest of the round. vote_solicitor prepares a round from the rep crawler and sends what the round planned, counting the messages that went out. The election loop keeps stamping pacing when a message is planned. * Stamp an election's pacing only for the messages that went out vote_solicitor::flush returns a solicitation_result naming, by winner hash, the elections whose winner broadcast or confirm_req a channel accepted. The election loop keeps the planned elections and stamps broadcast_sent and request_sent from the result, so a message a full or closed channel refused leaves its election due again next round instead of waiting out a whole interval. A broadcast that had no target, because every rep already voted for the winner, counts as done, otherwise the election would be planned again on every round. * Tidy the vote solicitor round The round keeps one list of representatives and a set of channels found full, instead of two copies of the list with one erased from while iterating. The decision helpers and their enum are private, the planned payloads get a vote_requests_t alias and a block_broadcast struct in place of a pair, a broadcast enters the result once whatever number of channels took it, and the round limits start from the struct defaults so each cap is spelled once. election_snapshot is forward declared. New tests pin the quorum difference between requests and broadcasts, a round without representatives, a full channel staying outside the per election cap, a partially refused flush, and the election loop asking again after a refused request. * Log and count what the vote solicitor drops A refused confirm_req or winner publish is logged at debug and counted as request_failed or broadcast_failed, the only solicitation events the election log cannot show. A successful confirm_req also counts the hashes it carried, and prepare counts rounds. The round now reports what planning decided against in its planning_counts: elections requested, channels found full, broadcasts no rep needed and broadcasts over the round cap. flush adds them to the stats as channel_full, no_targets and overfill, and sizes the result from the requested elections. * Send one request and one broadcast per channel for an election The rep crawler can hold several representative accounts behind one channel, a peer hosting more than one rep. The round planned a request and a winner broadcast per rep, so such a peer got the same hash repeated in one confirm_req and the same publish several times, and its duplicates took slots of the per election caps from other peers. Now the first rep that needs the election brings its channel in once. * Keep winner broadcasts no rep needs out of the round cap A broadcast whose every rep already voted for the winner sends nothing, yet it took one of the round's broadcast slots, so in a busy round it could crowd out an election whose winner still had to reach a rep. Such a broadcast is still planned and reported as done, but only a broadcast with targets counts towards the cap. Its election still hands the winner to the block rebroadcaster, which has its own cooldown. * Leave channels full for broadcasts out of winner broadcasts Vote requests skip a rep whose channel is full for confirmation requests, broadcasts planned a publish to every rep and left the full channels to drop it. The round now checks block_broadcast room the same way and leaves a full channel out for the rest of the round, without it taking a slot of the per election cap. When every rep that needs the winner is behind a full channel, the broadcast is not planned at all, so its election stays due instead of being reported as having nothing to send. The election loop queued the winner for the random flood only when the round planned its directed broadcast, so such a refusal would also have kept the winner from the flood, and a confirmed election, erased in the same round, would have lost its last broadcast for good. The loop now pushes the winner to the block rebroadcaster whenever the election asks for a broadcast and only then plans the directed one. The rebroadcaster dedupes blocks still in its queue and keeps a per hash cooldown, so an election that stays due costs nothing by pushing again every round. The round cap no longer holds the flood back either, the rebroadcaster has its own capacity check. * Take the vote solicitation caps from network_params The per election broadcast cap was half the network fanout, the size of the random block flood, which has nothing to do with how many principal representatives an election should push its winner to, and the round cap special-cased the dev network inline. All three caps are now a solicitation_constants group in network_params, next to the other component groups: 50 vote requests and 3 broadcasts per election and 30 broadcasts per round, with 1 and 4 broadcasts on the dev network. The broadcast values match what the fanout gave on the live and dev networks, a few hundred and a handful of peers. The group replaces the solicitor's own solicitation_limits, the round takes the network's caps as they are, and the solicitor no longer needs the network. * Plan solicitation against a per channel message budget The round asked every rep's channel for room once per rep per election and remembered the channels it found full in two sets, so later elections left them alone. The sets were the old solicitor's rule of erasing a rep from the round once its channel was full, carried onto a shared rep list, and the channel was still asked for every rep of every election. The round now asks each channel once when it starts and gives it a budget of messages per traffic type for the round, a solicitation constant sized to what a channel queue takes while below its max threshold. A channel already at max gets nothing this round. Requests spend the budget in confirm_req messages packed to the hash limit, broadcasts in winner blocks. A rep whose channel has no budget left is skipped without taking a slot of the per election cap, and such skips are counted as exhausted. The per round cap on winner broadcasts goes with it. It kept one round from flooding the channels with publishes, which the budget now bounds where it arises: a channel takes its budget of winner blocks and no more, and a round with many elections due spreads them over every channel that has room instead of stopping at a count. * Plan solicitation per channel and reach fork voters past the caps The round walked the reps one by one and stopped at the per election cap. A rep that voted for a different hash is exempt from the caps, but one ranked after enough ordinary reps was never looked at, so a light rep on the losing fork was neither asked again nor sent the winner. When a channel hosted both an ordinary rep and a fork voter, whichever ranked first decided whether its single message took a cap slot, which changed what the other channels got. The round now groups the reps by channel once, ranked by each channel's heaviest rep, and plans every election per channel. A channel takes the strongest decision among its reps, it is skipped, messaged outside the caps when a fork voter is behind it, or messaged against the cap. Once the cap is full, channels with a fork voter are still reached. The per channel budget applies to all of them as before, and a channel whose budget is spent counts as exhausted once rather than once per rep. * Spread directed winner broadcasts over random reps A new election is planned on its first tick before any vote arrived, so every node of the network sent its directed winner broadcast to the same few heaviest reps, while most of the weight never got a directed copy. A model of 65 principal reps with skewed weights and 200 nodes leaves 64% of the weight without one and puts every node's copy on each of the top three reps. The broadcast slots now go to channels picked at random among those missing the block, weight plays no part, so no rep draws a copy from every node. Fork voters' channels stay outside the cap. Vote requests keep the weight order, a lagging or forked node collects quorum from the heaviest reps and moving them out of the selection would cost exactly those. The round owns its random engine, seeded by the solicitor for every round and by a literal in tests. * Delay the directed winner broadcast after an election's first flood An election is planned on its first tick before any vote arrived, so its directed broadcast went to reps that had not seen the block only because it was a few milliseconds old, and most of them would have voted on the flooded copy anyway. The first broadcast of an election now only floods the winner through the block rebroadcaster. Pacing records it as flood only and makes the winner due again after block_broadcast_delay, a new network constant of about one confirmation request interval (5 s, 125 ms on the dev network). By then the snapshot shows which reps still lack a vote and the directed broadcast goes to those, an election that confirmed in the meantime sends none. Later broadcasts follow the block interval as before, and a new winner is due at once. The flood counts as the initial broadcast in the election stats and the directed broadcast after the delay as a repeat. * Cap and sample directed broadcasts to fork voters Reps that voted for a different hash were exempt from the per election broadcast cap, so every node sent the winner to every fork voter's channel on every directed broadcast, a full fan-out across the network for each election with a split vote. Fork voters' channels now have a cap of their own, election_fork_broadcasts (3, 1 on the dev network), and are sampled at random like the channels without a vote. Each node sends the winner to a few fork voters, the network as a whole still reaches all of them. Vote requests to fork voters stay outside the caps. * Cap vote requests to fork voters per election Channels with a rep that voted for a different hash were exempt from the per election request cap, so a set of reps voting for the other side on many elections had every node add a hash for each of them on every request interval, with nothing bounding it per election. Fork voters' channels now fill a cap of their own, election_fork_requests (10), heaviest first like the other requests and apart from them, so they never take slots from the reps without a vote. The heaviest fork voters, the ones that decide whether quorum flips, are always asked, a crowd of light ones is cut off at the cap. * Leave reps with a final vote for another hash out of solicitation A final vote never changes: a rep stores it and answers every later request with the same vote. A rep whose final vote went to a different hash was still asked for votes and sent the winner block on every round, which could only repeat that vote. Such a rep is now skipped for vote requests and winner broadcasts. A fork voter with a non-final vote can still switch and keeps being asked and sent the block, under the fork caps. * Pace winner floods and directed broadcasts on their own schedules An election's broadcast action covered both the flood through the block rebroadcaster and the directed broadcast to reps, with the first one flood only, so the election loop had to branch on which of the two a broadcast was. The flood was also recorded whatever the rebroadcaster did with it, so a flood it refused still started the directed delay, and a confirmed election erased that round could end up with no winner broadcast at all. Pacing now keeps two schedules. A flood is due when none went out yet, after the block interval or for a new winner. A directed broadcast is due once the block delay passed since the winner's latest flood, then after the block interval or for a new winner, which now also waits for its flood. The election emits the two as separate actions and the loop handles them independently. A flood counts only when the rebroadcaster takes the block: push returns true when it queued the block or already had it queued, false when it is disabled or full, and a winner it did not take stays due and is pushed again next round.
__________
Type: commit
Hash: b462795efd11bc6263839a9ca873794e67a0d843
Created: today
__________
gr0v1ty/nano-node:b462795efd11bc6263839a9ca873794e67a0d843
| Test Case | Status | Duration | Median Deviation | Log | Graph |
|---|---|---|---|---|---|
| No test results available yet. Check the GitHub test run for job status and logs. | |||||