Scalable Moderation using a web-of-trust model

In this thread, let’s discuss Freenet’s web-of-trust based strategy shared in this post:

What I’d like to do is break implementation down into a number of small problems to solve, for which an issue will be created.

If you wish to pursue another solution, please create a thread and link it below. That way this thread can be focused on the solution above while overall helping to make progress on the problem.

Active repos:

Resources:

Reply with a link to have yours added.

1 Like

Maybe I can cut that down somewhat, because I already started some of the work: ~arnebab/wispwot - sourcehut hg

This is not yet finished, though. The goal is to have a simple REST server that any instance can use, even between different networks.

Longterm-plan: Expose a REST-service with the following actions:

  • PUT an ID with trust values (trustee-ID,trust).
  • GET an ID to receive its score.
  • GET a list of IDs to check for update of trust and/or content.
  • PUT new trust values directly (truster-ID,trustee-ID,trust) for fine-grained trust-control.
  • POST a list of IDs you requested without seeing a change.

PUT of changed IDs and POST of lists of unchanged IDs drive the state
of the WoT.

1 Like

It would be great to get a calculation on resources required for each of the 10k instances of the fediverse (podupti.me/stats) to store the necessary data and to propagate updates.

My understanding of Mastodon and Diaspora is that each server only cares about remote users that are followed by someone local. But then content that is replied to or boosted comes through and represents a new ID on which to resolve trust.

Also wanted to add a link that I found earlier when someone proposed WoT for Mastodon. "Trust Propagation" can fix the internet. Let's be at the forefront. · Issue #10096 · mastodon/mastodon · GitHub

1 Like

For propagating updates:

On the surface the maximum number of polls would be 1 request every two seconds per user. Boosting should not change this, because it is still social interaction, so it ist part of the calculation.

A very naive approach would be to see that my browser fires 20-30 requests per second when accessing the website of the Washington post. So up to 60 users, this should work even with very inefficient formats without any optimization.

I am not sufficiently well-versed in the interactions between mastodon instances to estimate how well they can reduce the requests by pooling per instance.

The worst-case would be following one user per instance, so nothing could be optimized on instance-level.

For the stored data:

Theory:

In the implementation I wrote, adding a trust connection to a known ID requires 3 bytes (u16 index to id and i8 trust) in memory and 14 bytes in non-optimized plaintext storage on disk.

Adding a trust-connection to an unknown ID requires roughly 100 bytes in memory (depending on the representation of the reference to the ID) and 120 bytes in unoptimized plaintext storage.

Measured:

this is not optimized yet, more than 60% of the project is still to do, so this is just a prototype

I tested that in my current implementation with 16k IDs with 200k trust relationships from the real Freenet Web Of Trust data (3.2MiB on disk, using only integers instead of URIs to reference IDs to reduce the size from 300MiB to something usable) this currently requires 120 MiB in memory (most of that due to delayed garbage collection) and adding all trust relationships one by one without score recomputation requires 60 minutes of CPU time.

The full score computation is not yet optimized, though: Calculating all scores for all IDs a very well-connected user knows up to 9 steps away currently take a few seconds.

Keep in mind though, that this is still missing essential optimizations, so it gets slower with increasing size of the WoT. Missing are:

  • Incremental score recomputation from the existing WoT-Code in Freenet (gets recomputation on adding down to the tens of milliseconds area, but is quite complex) and
  • bounded polling and pruning stale IDs from the scalability calculation (pruning stale IDs reduces the number of IDs to track, so it speeds up everything).
1 Like

The memory consumption will be roughly doubled if you lift the restrictions to track at most 64k IDs per instance (using u32 indexes then instead of the current u16 indexes).

The incremental recomputation is what the WoT bachlor thesis is about: plugin-WebOfTrust/OadSFfF-version1.2-non-print-edition.pdf at 4fdcc56558b4a64facc9b7ab25d695765356ca69 · xor-freenet/plugin-WebOfTrust · GitHub

I am wondering how far we need to go with a ranking system.
Naively, I would expect self-moderation to require a much smaller amount of data:

  • you manually pick people or instances you trust (maybe assigning them a integer or real trust level but that may not even be necessary)
  • you automatically block people that are blocked by these trusted users

I am not sure trust brings much valid information on general networks like the Fediverse where users you’d trust about a subject can say utterly stupid things about another.
Since we do not have a single topic or use case (such as for couch surfing or website selling stuff), I fear a general ranking system may be more counter productive than anything else (but I’d be happy to discuss it and potentially change my mind).

For a simpler implementation such as the one I mentioned (maybe more akin to friendship circles), the computation required to automatically block people is much simpler:

  • block anyone blocked by your best friends
  • block anyone blocked by more than N of your more distant friends

This only requires a very small number of additional requests and virtually no computation.

I’ve been thinking about this problem for a while (10+ years)

While I dont have a full solution, perhaps I could approach it from a certain angle:

Moderation / reputation systems classically encourage good behaviour, discourage bad behaviour and provide a metric

  1. Encourage good behaviour – I have the idea that a user could obtain credits for a post that people like, something that’s like spendable karma. You can pass this on to other users, in other instances. Those people in turn can use it to mark other users, or spend on resources. It’s a concept we’ve called ‘marking’ a user – something that goes beyond a ‘thanks’ or ‘like’ – it is said that gratitude is the completion of a thanks. Gratitude is one of the things imho that is under developed on the web. The credits should be fair and hard to obtain, also should not favour any given party able to print tokens. A good example of this would be the lightning network

  2. Discourage bad behaviour – this is a hard problem, especially given things like ‘insult’ laws. There is the concept of ‘altruistic punishment’ that research has shown to improve outcomes. The idea is that you can penalize bad behaviour (perhaps anonymously) using the same credit system, but the credits the are given back to the whole community. A fascinating TED talk on this topic (time is set)

  1. Provide a metric – this can be a ranking system or high score table. The community itself set the metric of how the data is ranked. You separate the marking data into a JSON blob, and then apply an algorithm. This could be making ranking exponentially harder to obtain, or be time decayed, etc. This would encourage users to become the best members of the group leading to more high quality engagement. A bit like discourse but more concrete.

We did a pilot for this and it worked very well

Each community could do its own thing, and federate with others

Technically you would need a simple data model to record a (signable) marking (start with plain old json, then add a vocab). I’d very much encourage a simple object rather than a nested object, as the complexity is an OOM easier that way. An algorithm to generate the rankings, and UI features to add and moderate posts. Further work could include privacy controls: anonymous, private, shared, public

1 Like

Please excuse my questions at the beginning if they are too simple, but I don’t want to gloss over anything that might create confusion later.

How do you arrive at 1 request every two seconds per user? Or is that a requirement you’re starting with?

I feel like instances may be better to model as containers of user ids since my assumption, which is also open for discussion, is that most of the activity in updating the WoT would consist of server-to-server updates. Perhaps limited in the same ways as you describe for Freenet, with N of one kind of update, M of several other kinds of updates, etc.

This is premature optimization talk but indexing implies storage for each server in a way that would need mapping if it where shared with other servers. I wonder if indexing by a native id (like weex@c4.social or even the public key) would be a useful tradeoff for implementations to make.

One way I thought about this in the past was that I just wanted a bullshit button, and to have pressing that have repercussions in a WoT. One of my favorite AI researchers, Joscha Bach observed that social media seems only to have amplification, putting networks in a constant state of seizure. A bullshit button, or just negative ratings, helps provide the attenuation needed for more balance.

On the topic of a ranking system being counter productive, I’d like to encourage people to try things and see what works. “Nobody knows anything” is a helpful way to get past arguments when code could be written and experiments can be done.

I’m interested to see Freenet’s system implemented since it seems to have worked, but ideally there would be several WoT implementations in different languages, as standalone daemons, or as plugins so markets of users and communities can converge on what works best.

I really like the idea that no additional user action is necessary. Boosts and replies and favorites are positive. Blocks are negative. Maybe a bullshit button as I mentioned above could be one add-on, but from there any number of implementations could be done so we can see what works.

Thanks for the TED talk link! Not sure if applicable but the punishment aspect was most intriguing.

For those playing at home, do you have a link to a write-up on this?

1 request per 2 seconds is the result of the scaling calculation you link to. The question I’m not sure about is how much instances can reduce this cost by requesting multiple pieces of information from other instances in one request.

If you have 1000 users, you’d otherwise hit 500 requests to send per second, and that could quickly be too high load for instances.

I think than once you add a currency (or any global metric), you create perverse incentives to game how you appear to others.

In Freenet there is blocking: If you downvote someone, the effect is that they disappear to people who trust you: start to spam and you lose visibility, so there is no point to spamming.

@tfardet the difference to your model is that blocking by more distant friends is given lower weight, and that you only see those your friends marked as trustworthy (replied or boosted).

A simplification for mastodon could be to only use this system for remote accounts: On your own instance you can easily moderate by actually blocking people instancewide, and you can get instant visibility. For interaction with people from other instances that’s harder. Their values might be different, but you still want to see some people from that group.

In what I wrote it doesn’t matter for the system how you identify accounts. You ask the system whom to check and it returns you the identifier you gave it.

@ArneBab In regards to the code you linked, will it generate some random data for testing or do you need some kind of input db to try it?

Setup didn’t work for me on mac or debian 11. I think I’m just missing some package setup wispwot error · GitHub

Maybe my reply was not properly worded: I did not mean we should not try anything, on the contrary.
It’s just that ranking-based WoT seems hard to implement and scale so I was proposing a potentially lighter way to test something out with (I think) only minor modifications to existing code, namely:

  • adding trust relations (like follow but for blocks)
  • propagating block notifications to trusting users (note that this probably requires trust to be requests that would have to be accepted by the trusted users, otherwise it can become a way to spy on who people are blocking)
  • adding automatic block based on receive block information

(note that it can work for both users and instances)

1 Like

OK, I did not think you’d take the “negative gain” that far, I thought the default behavior would still be to show untrusted sources and only hide “distrusted” sources.

I really like the minimal addition idea. It’s certainly a vote for adding directly into instance software. Perhaps a checkbox can disable it all for those who wish to take another route.

Notifications or approvals might not even be required if we’re talking about calculations that occur internal to a server based on already-supplied user data.

Also agree that a WoT shouldn’t leak information about blocks but it can be hard to avoid for very small networks.

I’d also make a distinction between sensing and visibility. It’s one thing to see that someone is a spammer or shares lies but it should still be possible to view such content to ensure it’s not censorship from your own perspective. Much like Twitter started decorating some posts, I would appreciate an option as a user that shows me everything but makes it clear in the UI that my WoT doesn’t like this post.

1 Like

The code uses an actual snapshot of the WoT in Freenet for testing: The Freenet social trust graph extracted from the Web of Trust

The dependencies are autoconf, automake, make, bash and guile. Do you have them installed? I saw that I did not add m4/ and aclocal.m4 — can you pull and try again?