|
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();
|
|
}
|
|
} |