Skip to content

Instantly share code, notes, and snippets.

What would you like to do?

Pseudonym Pairs: A foundation for proof-of-personhood in the web 3.0 jurisdiction

Author: BipedalJoe, Year 18

Pseudonym Pairs is a dApp for global proof-of-personhood, through monthly pseudonym events that last 20 minutes, where every single person on Earth is randomly paired together with another person, 1-on-1, to verify that the other is a person, in a pseudo-anonymous context. The events provide NYM tokens, global personhood tokens, untraceable from month to month and disposable, a sort of “temporary access tokens” similar to festival bracelets. The proof-of-personhood is that you are with the same person for the whole event.

1-on-1 verification of (pseudo-anonymous) personhood

Within the 1-on-1 pairs, people can socialize as they want, and can be seen as being employed in government positions, expected to stay within the pair for the entire duration of the pseudonym event. The 1-on-1 pairs is the standard organization, requiring mutual verification. In the case of a problem, such as a bot attacker, or, a person not showing up, people can break up their pair, to be assigned to be verified by another pair (2-on-1), similar to how people are verified at the “virtual border”. (see below)

How to opt-in to Pseudonym Pairs

The population is used to secure a "virtual border" around the network, and “border tokens” (BDR) can be bought to apply at the “virtual border” and meet a random pseudonym pair, that verify the person that opts-in. The “border tokens” are distributed through the population, each person can issue 1 BDR, and each time BDR is issued, the ability to issue one more BDR is given to a random person within the pseudonym pool, distributing the ability to invite new people onto the population as a whole, making it possible for the network to accept new people multiple times its population size, so that it can grow from 0 to potentially 5 billion people.

Self-regulation of new people joining the network

The Pseudonym Pairs network as a collective or swarm is able to self-regulate a "virtual border" around itself, so that people may opt-in and opt-out, and the regulatory system also lets the population grow initially from a few people to billions of people.

struct ShuffleAlgorithm {
    uint[] index;
    uint counter;
ShuffleAlgorithm airdropBDR;

mapping(uint => uint) allocationBDR;

function airdropBorderToken() internal {
    uint randomNumber = airdropBDR.counter + labyrinth.generateRandomNumber() % (totalVerified + 1 - airdropBDR.counter);
    if(airdropBDR.index[randomNumber] == 0) airdropBDR.index[randomNumber] = randomNumber;
    if(airdropBDR.index[airdropBDR.counter] == 0) airdropBDR.index[airdropBDR.counter] = airdropBDR.counter;
    allocationBDR[airdropBDR.index[randomNumber]] += 1;
    airdropBDR.index[randomNumber] = airdropBDR.index[airdropBDR.counter];
    if(airdropBDR.counter == totalVerified) delete airdropBDR;

The population sorts themselves into pairs

The pair sorting is invoked by each person, people are sorted into two lists (together forming pairs), and the lists are continuously shuffled with each new person who invokes sortMe(). This sorting mechanism keeps the computational cost per person low, and forms complete pairs regardless of how many of the people who registered choose to commit with sortMe().

function sortMe() atTime(0, pseudonymEvent) {
    uint8 idx;
    uint totalSorted = pairingUtility[0].counter + pairingUtility[1].counter;
    if(totalSorted % 2 == 1) {
        idx = 0;
    else {
        idx = 1;
    pseudonymID[msg.sender] = totalSorted;
    uint pos = pairingUtility[idx].counter;
    uint randomNumber = 1 + labyrinth.generateRandomNumber() % (pos - 1);
    pairingUtility[idx].index[randomNumber] = pos;

Borderless personhood tokens for a global population

The Pseudonym Pairs protocol has no way of distinguishing between people, since it treats any human being as equivalent, it cannot shut certain people out. It is borderless in that the protocol cannot know how many people it has counted unless it assumes it is everyone.

The personhood tokens are mixed, making them untraceable

When the pseudonym event is over and people have been verified, all personhood tokens are mixed, through the entire population. The mixing is simple, people continuously join mixers, incrementally increasing the number of mixers over time as people invoke joinMixer(), and a personhood token is issued to their new public key.

function joinMixer() {
    require(publicKey[msg.sender][0] != 0);
    require(mixerIndex[msg.sender] == 0);
    mixerIndex[msg.sender] = mixerCount;
    uint index = mixer[mixerCount].length;
    uint mixerSize = getMixerSize();
    if(index == mixerSize) { mixerCount++; }

Profitability of collusion attacks

The only attack vector on the system is collusion attacks, a population of colluding people can over-number the randomization of pairs, and gain control of majority in a percentage of all pairs, two people in a pair, freeing those people to show up as a single in another pair or at the “virtual border”. That lets the colluding population sustain a population of bots and provide those bots with personhood tokens.

The profitability of the attack is quite low, the randomization of pairs from a global population, and the 1-on-1 pairs requiring 100% majority to be “hijacked”, means that a colluding population will get control of proportionally much fewer pairs than there are people in the colluding population. If 10% of the population collude, they get around 0.5% of all pairs under bot control, 0.05x a personhood token per person attacking.

This attack is identical to a colluding population selling their positions in pairs to bots, and then buying border tokens, and being verified that way, and that particular attack could be prevented by adding an extra month for opting-in. Since an equivalent attack is possbile even with an extra month, no need for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment