The POI anti-sybil protocol
Pseudonym parties are based on the fact that you cannot be in two places at once. Global pseudonym party events happen in synchrony, simultaneously all over the world, and are scheduled continuously throughout the year. The earliest reference for the protocol that I've found is from 2007/2008, https://pdos.csail.mit.edu/papers/accountable-pseudonyms-socialnets08.pdf
The POI protocol takes the pseudonym party concept into the digital space, using video chats instead of IRL meetups. The underlying proof is of the same kind, that people cannot be in two embodiments at once.
The protocol is agnostic about how people verify one another in the hangouts. It's anonymous in the sense that people could even wear Guy Fawkes masks and it would still work, as they could use arm-motion mimicry to verify joint-attention. The POI tokens themselves are completely a-personal, and not traceable over time. Each new POI token you receive is not traceable to your previous one. It's an anonymous proof-of-individuality that gives you complete sovereignty over your digital self.

Randomized pseudonym parties using video hangouts
contract poi {
bool debug;
uint blockNum;
uint groupSize;
bytes32 entropy;
uint public numUsers;
mapping(address => bytes32) public userHash;
//mapping(bytes32 => address) public userAddress;
mapping(address => uint) public userGroup;
// max value of a sha3 hash
bytes32 maxHash = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
enum Phases { Registration, Commitment, Verification }
event Registration(bytes32 userHash);
event Commitment(bytes32 userHash, uint group);
event Verification(bytes32 userHash);
Phases phase;
uint public genesisBlock;
uint public registrationBlock;
uint public commitmentBlock;
uint public validityBlock;
function blockNumber() constant returns(uint){ if (debug) { return blockNum; } return block.number; }
function numGroups() constant returns(uint){ return numUsers / groupSize;}
function poi(){
debug = true;
groupSize = 5;
entropy = sha3(block.blockhash(block.number));
genesisBlock = block.number;
registrationBlock = genesisBlock + 7;
commitmentBlock = registrationBlock + 3;
validityBlock = commitmentBlock + 20;
phase = Phases.Registration;
}
function register() returns(bool success){
if ((blockNumber() > registrationBlock) // registation period over
|| (userHash[msg.sender] != bytes32(0))) return; // already registered
// generate a hash for the given user, using previous entropy,
// senders address and current blocknumber.
bytes32 h = sha3(entropy, msg.sender, block.blockhash(block.number));
entropy = h;
userHash[msg.sender] = h;
//userAddress[h] = msg.sender;
numUsers++;
Registration(h);
return true;
}
function commit() returns(bool success){
if ((blockNumber() < registrationBlock) // registation period not yet over
|| (blockNumber() > commitmentBlock) // commitment period over
|| (userGroup[msg.sender] != 0)) return; // group already assigned
phase = Phases.Commitment;
// deterministically assign user to random group (1-indexed)
// based on number of users, group size and user hash;
userGroup[msg.sender] = uint(userHash[msg.sender]) / (uint(maxHash) / numGroups()) + 1;
Commitment(userHash[msg.sender], userGroup[msg.sender]);
return true;
}
function verify(bytes32 data, uint8 v, bytes32 r, bytes32 s ) returns(bool success){
if ((blockNumber() < commitmentBlock) // commitment period not yet over
|| (blockNumber() > validityBlock) // verification period over
|| (userGroup[msg.sender] == 0)) return;
phase = Phases.Verification;
// TODO :)
address signer = ecrecover( data, v, r, s);
// is the proof provided by a user in the same group
if (userGroup[signer] == userGroup[msg.sender]) {
Verification(userHash[msg.sender]);
return true;
}
}
function _incBlock() { if (debug) blockNum++; }
function _myAddressHelper() constant returns(address){ return msg.sender; }
function _myGroupHelper() constant returns(uint group) {
return userGroup[msg.sender];
}
}
Anonymous and untraceable POI tokens
POIs are indexed on the block-chain and searchable, and you could build more complex IDs on top of it. A POI in itself is anonymous and controlled by the owner who has the corresponding private key. You can link your POIs together, at the cost of decreased anonymity.

/* component of the Proof-of-individuality (POI) system. Generates new POIs each month, anonymous and un-traceable */
contract generatePOItokens{
address owner;
string public name;
string public symbol;
uint8 public decimals;
mapping (address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 value);
function generatePOItokens(address[] verifiedUsers) {
owner = msg.sender;
balanceOf[owner] = verifiedUsers.length; // Give the creator all initial tokens
name = "POI"; // Set the name for display purposes
symbol = "POI"; // Set the symbol for display purposes
decimals = 0; // Amount of decimals for display purposes
/* Send POIs to every verified address */
for (uint i = 0; i < verifiedUsers.length; i++)
balanceOf[owner] -= 1;
balanceOf[verifiedUsers[i]] += 1;
Transfer(owner, verifiedUsers[i], 1); // Notify anyone listening that this transfer took place
}
function depricatePOIs() {
if (msg.sender == owner) suicide(owner);
}
}
contract POIscheduler{
address[] verifiedUsers;
address POIaddress;
uint public genesisblock;
uint public roundLength;
uint public nextRound;
function POIscheduler(){
owner = msg.sender;
genesisblock = block.number;
roundLength = 3000; // set POI pseudonym parties to happen once a month
nextRound = genesisblock + roundLength;
scheduleCall();
}
function issuePOIs() {
if(block.number<nextRound)
throw;
// depricate old POIs
generatePOItokens(POIaddress).depricatePOIs();
POIaddress = new generatePOItokens(verifiedUsers);
/* schedule a new POI round one month from now */
nextRound += roundLength;
scheduleCall();
}
function scheduleCall() public {
/* ethereum-alarm-clock is a DAO for excecuting scheduled calls */
address scheduler = 0x26416b12610d26fd31d227456e9009270574038f; // alarm service v0.7 on the morden testnet
// the 4-byte signature of the local function we want to be called.
bytes4 sig = bytes4(sha3("issuePOIs()"));
// approximately 1 month from now
uint targetBlock = nextRound;
// the 4-byte signature of the scheduleCall function.
bytes4 scheduleCallSig = bytes4(sha3("scheduleCall(bytes4,uint256)"));
scheduler.call(scheduleCallSig, sig, targetBlock);
}
function verifyPOI (address v) constant returns (string){
if (generatePOItokens(POIaddress).balanceOf[v]==0){
return "account does not have a valid POI";
}
return "account has a valid POI";
}
}
Anti-Sybil Fuel (ASF)

/*
Anti-sybil fuel (ASF) is used to gamify the POI hangouts. Participants can
use it to "hijack each other's attention", which makes it easier for the
POI community to keep high standards. Each user gets 5000 "anti-sybil fuel" points,
and then rewards the other 4 users for their attention. This makes it possible
for 4 people to put peer-pressure on the 5th if the 5th person isn't focused
on the joint attention test.
*/
contract AntiSybilFuel {
uint public genesisblock;
uint public deadline;
struct ASF {
uint256 initial_supply;
uint256 rewarded;
uint256 given;
}
mapping (address => ASF) public ASFbalances;
address[] participants;
function AntiSybilFuel(address[] hangoutGroup) {
for (uint i = 0; i < hangoutGroup.length; i++)
ASFbalances[hangoutGroup[i]].initial_supply += 5000;
groupMembers.push(hangoutGroup[i])
genesisblock = block.number;
deadline = genesisblock + 3000; // hangouts are 15 minutes long
}
function rewardASF(address _to, uint256 _value) {
/* If the sent amount is bigger than the maximum amount one can give, send max amount */
if (ASFbalances[msg.sender].given + _value >5000)
_value = _value-((ASFbalances[_to].rewarded+_value)-5000);
/* If the sent amount is bigger than the maximum reward limit, send max amount */
if (ASFbalances[_to].rewarded + _value >5000)
_value = _value-((ASFbalances[_to].rewarded+_value)-5000);
/* transfer the anti sybil fuel */
ASFbalances[msg.sender].given +=_value;
ASFbalances[_to].rewarded +=_value;
ASFbalances[msg.sender].initial_supply -=_value;
}
/* after 15 minutes, each users that has been awarded 4000 ASF or more, and
given out 4000 or more, is seen as verified and given a POI token */
/* the closeSession function can be called by anyone in the hangut once the deadline has passed */
function closeSession(){
if(block.number<deadline) throw;
for(uint i = 0; i < participants.length; i++)
if(participants[i].given >4000 && participants[i].rewarded >4000)
address[] verifiedUsers.push(participants[i])
*/ pass verifiedUsers into a contract that generates POIs, together with verifiedUsers from all other hangouts */
POI(address).listVerifiedUers(verifiedUsers)
*/ the POI contract will then pass the full list into the contract generatePOItokens */
}
}