contract OnlinePseudonymParties { uint entropy; function getRandomNumber() internal returns (uint){ return entropy = uint(keccak256(abi.encodePacked(blockhash(block.number - 1), entropy))); } uint constant public period = 4 weeks; function schedule() public view returns (uint) { return 198000 + ((block.timestamp - 198000) / period) * period; } function hour(uint _t) public pure returns (uint) { return uint(keccak256(abi.encode(_t)))%24 * 1 hours; } enum Rank { Court, Pair } enum Token { Personhood, Registration, Immigration } struct Reg { Rank rank; uint id; bool verified; } mapping (uint => mapping (address => Reg)) public registry; mapping (uint => address[]) public shuffler; mapping (uint => mapping (Rank => mapping (uint => bool[2]))) public judgement; mapping (uint => mapping (uint => bool)) public disputed; mapping (uint => mapping (address => bool)) public proofOfUniqueHuman; mapping (uint => mapping (Token => mapping (address => uint))) public balanceOf; mapping (uint => mapping (Token => mapping (address => mapping (address => uint)))) public allowed; function registered(uint _t) public view returns (uint) { return shuffler[_t].length; } function register() public { uint t = schedule(); require(registry[t][msg.sender].id == 0 && balanceOf[t][Token.Registration][msg.sender] >= 1); balanceOf[t][Token.Registration][msg.sender]--; uint id = 1; if(registered(t) != 0) { id += getRandomNumber() % registered(t); shuffler[t].push(shuffler[t][id-1]); registry[t][shuffler[t][id-1]].id = registered(t); } else shuffler[t].push(); shuffler[t][id-1] = msg.sender; registry[t][msg.sender] = Reg(Rank.Pair, id, false); } function immigrate() external { uint t = schedule(); require(registry[t][msg.sender].id == 0 && balanceOf[t][Token.Immigration][msg.sender] >= 1); balanceOf[t][Token.Immigration][msg.sender]--; registry[t][msg.sender].id = 1 + getRandomNumber()%(2**256-1); } function isVerified(Rank _rank, uint _unit, uint _t) public view returns (bool) { return (judgement[_t][_rank][_unit][0] == true && judgement[_t][_rank][_unit][1] == true); } function dispute(bool _premeet) external { uint t = schedule() - period; if(_premeet == false) t -= period; require(registry[t][msg.sender].rank == Rank.Pair); uint id = registry[t][msg.sender].id; uint pair = (id+1)/2; if(_premeet == false) require(!isVerified(Rank.Pair, pair, t)); disputed[t][pair] = true; } function reassign(bool _premeet) external { uint t = schedule() - period; if(_premeet == false) t -= period; uint id = registry[t][msg.sender].id; uint pair = 1 + ((id - 1)/(uint(registry[t][msg.sender].rank) + 1))%registered(t)/2; require(disputed[t][pair] == true); delete registry[t][msg.sender]; registry[t][msg.sender].id = 1 + uint(keccak256(abi.encodePacked(msg.sender, pair)))%(2**256-1); } function _verify(address _account, address _signer, uint _t) internal { require(block.timestamp > _t + hour(_t)); _t -= period*2; require(registry[_t][_signer].rank == Rank.Pair && _account != _signer); Rank rank = registry[_t][_account].rank; uint temp = (registry[_t][_account].id-1)/(1 + uint(rank)); uint unit = 1 + temp; uint pair = 1 + temp%registered(_t)/2; require(disputed[_t][pair] == false); uint peer = registry[_t][_signer].id; require(pair == (peer+1)/2); judgement[_t][rank][unit][peer%2] = true; } function verify(address _account) external { _verify(_account, msg.sender, schedule()); } function uploadSignature(address _account, bytes32 r, bytes32 s, uint8 v) external { uint t = schedule(); _verify(_account, ecrecover(keccak256(abi.encodePacked(_account, t)), v, r, s), t); } function completeVerification() external { uint t = schedule()-period*2; require(registry[t][msg.sender].verified == false); uint id = registry[t][msg.sender].id; uint pair; if(registry[t][msg.sender].rank == Rank.Court) { require(isVerified(Rank.Court, id, t)); pair = 1 + (id - 1)%registered(t)/2; } else pair = (id + 1) /2; require(isVerified(Rank.Pair, pair, t)); balanceOf[t+period*2][Token.Personhood][msg.sender]++; balanceOf[t+period*2][Token.Registration][msg.sender]++; balanceOf[t+period*2][Token.Immigration][msg.sender]++; registry[t][msg.sender].verified = true; } function claimPersonhood() external { uint t = schedule(); require(proofOfUniqueHuman[t][msg.sender] == false && balanceOf[t][Token.Personhood][msg.sender] >= 1); balanceOf[t][Token.Personhood][msg.sender]--; proofOfUniqueHuman[t][msg.sender] = true; } function _transfer(uint _t, address _from, address _to, uint _value, Token _token) internal { require(balanceOf[_t][_token][_from] >= _value); balanceOf[_t][_token][_from] -= _value; balanceOf[_t][_token][_to] += _value; } function transfer(address _to, uint _value, Token _token) external { _transfer(schedule(), msg.sender, _to, _value, _token); } function approve(address _spender, uint _value, Token _token) external { allowed[schedule()][_token][msg.sender][_spender] = _value; } function transferFrom(address _from, address _to, uint _value, Token _token) external { uint t = schedule(); require(allowed[t][_token][_from][msg.sender] >= _value); _transfer(t, _from, _to, _value, _token); allowed[t][_token][_from][msg.sender] -= _value; } function initialize() external { uint t = schedule(); require(registered(t-period*2) < 2 && registered(t) < 2); balanceOf[t][Token.Registration][msg.sender]++; register(); } }