Long term project: feedback loop to dynamically adjust bridge pool sizes (inspired by proximax)
Now that we have bridgestrap working, and we are ramping up our in-country deployments for assessing which bridges are getting blocked, we're back in position to reach another long-wanted milestone for the bridge distribution system. The proximax-inspired bridge distribution "meta-strategy" is simple to explain: keep track of which bridge distribution strategies are effective, and automatically send new bridges toward the strategies that are succeeding.
As described in the "five ways to test bridge reachability" blog post:
"We can define the efficiency of a bridge address in terms of how many people use it and how long before it gets blocked. So a bridge that gets blocked very quickly scores a low efficiency, a bridge that doesn't get blocked but doesn't see much use scores a medium efficiency, and a popular bridge that doesn't get blocked scores high. We can characterize the efficiency of a distribution channel as a function of the efficiency of the bridges it distributes. The key insight is that we then adapt how many new bridges we give to each distribution channel based on its efficiency. So channels that are working well automatically get more addresses to give out, and channels that aren't working well automatically end up with fewer addresses."
Many more details in that blog post (https://blog.torproject.org/research-problem-five-ways-test-bridge-reachability/) and in the original research paper (https://www.freehaven.net/anonbib/#proximax11).
In terms of roadmap, here are possible steps.
Phase one, getting the building blocks in place:
-
Pick a utility function for how to assess a given bridge. Start with something simple and then iterate. For example, "current number of users times number of days we've been giving it out and it's been unblocked." A later more complex function might be "for each country where it has users, add up the (# of users in that country times the number of days it's been reachable from that country)." A third iteration might be to assign a per-country weight multiplier based on how much blocking the country is experiencing, how much we want to prioritize that country, etc. Another idea is to look at bandwidth use (more is better) in addition to simple user count. -
Work with the metrics team to make decisions about the data architecture. Calculating bridge scores involves looking at historical info about bridges, and bridge usage, and bridge reachability. Maybe this is all better done inside onionoo -- and then the rest of the metrics pipeline like relay-search is in a better position to use it too. -
Pick a composite utility function for how to assess a given distribution stategy given scores for each bridge in its pool. Again start simple, for example "add up the utility scores for each bridge in that pool." -
Take a step back: Examine the scores we have, and see if it matches our intuition. Retune the utility functions. Put up some ongoing graphs on the metrics pages. The per-strategy summary scores are already useful at this point, to let us and others see which strategies are being effective.
Phase two, automating the feedback loop:
-
Research: based on the above experience, invent utility functions which are both effective and more robust to gaming. In particular, consider how to handle attacks where colluding bridges report inflated user counts, to make a given distribution strategy look better than it really is. And make sure our utility functions converge, rather than e.g. letting one strategy's score grow so it gets more bridges so it grows more and pretty soon it's at infinity. -
Research: decide how to adjust the allocations for a new bridge: given the existing pool sizes, and the current composite utility functions, which pool should a new bridge be given to? I bet complex systems control theory has some suggestions here. -
Monitor it all to make sure it continues behaving as we expect.
In particular, one of the key features of this approach is that we can easily add new external bridge distribution mechanisms, such as this week's new "Salmon lite" from the Russian hackathon: we give them a "seed" pool of initial bridges, and then their approach sinks or swims on its own without any need for manual evaluation or centralized adjustments at the rdsys level.