add a kind of querying to resolveCustom

add a kind of querying to resolveCustom

pragma solidity ^0.4.16;

interface JudgeInterface {
    function judge(bytes32[13] res, uint q,
                        bytes32[] _proof, bytes32[] _proof2,
                        bytes32 vm_, bytes32 op, uint[4] regs,
                        bytes32[10] roots, uint[4] pointers) public returns (uint);
    function judgeFinality(bytes32[13] res, bytes32[] _proof, bytes32[] _proof2,
                        bytes32[10] roots, uint[4] pointers) public returns (uint);
    function judgeCustom(bytes32 state1, bytes32 state2, bytes32 ex_state, uint ex_reg, bytes32 op, uint[4] regs, bytes32[10] roots, uint[4] pointers, bytes32[] proof) public;

    function checkFileProof(bytes32 state, bytes32[10] roots, uint[4] pointers, bytes32[] proof, uint loc) public returns (bool);
    function checkProof(bytes32 hash, bytes32 root, bytes32[] proof, uint loc) public returns (bool);

    function calcStateHash(bytes32[10] roots, uint[4] pointers) public returns (bytes32);
    function calcIOHash(bytes32[10] roots) public returns (bytes32);
}

interface CustomJudge {
    // Initializes a new custom verification game
    function init(bytes32 state, uint state_size, uint r3, address solver, address verifier) public returns (bytes32);

    // Last time the task was updated
    function clock(bytes32 id) public returns (uint);

    // Check if has resolved into correct state: merkle root of output data and output size
    function resolved(bytes32 id, bytes32 state, uint size) public returns (bool);
}

contract Interactive2 {

    JudgeInterface judge;

    mapping (uint => uint) blocked;
    mapping (uint => bool) rejected;

    enum State {
        Started,
        Running, // First and last state have been set up ... but this will mean that the verification game is running now
        Finished, // Winner has been chosen
        NeedErrorPhases,
        NeedPhases,
        PostedErrorPhases,
        PostedPhases,
        SelectedErrorPhase,
        SelectedPhase,

        /* Special states for finality */
        Finality,
        Custom
    }

    struct Record {
        uint256 task_id;

        address prover;
        address challenger;

        bytes32 start_state; // actually initial code + input
        bytes32 end_state; // actually output

        // Maybe number of steps should be finished
        uint256 steps;

        address winner;
        address next;

        uint256 size;
        uint256 timeout;
        uint256 clock;

        uint256 idx1;
        uint256 idx2;

        uint256 phase;

        bytes32[] proof;
        bytes32[13] result;

        State state;

        //
        CustomJudge judge;
        bytes32 sub_task;
        bytes32 ex_state; // result from the custom judge
        uint ex_size;
    }

    function Interactive2(address addr) public {
        judge = JudgeInterface(addr);
    }

    mapping (bytes32 => Record) records;
    mapping (uint64 => CustomJudge) judges;

    // who should be able to
    function registerJudge(uint64 id, address addr) public {
        judges[id] = CustomJudge(addr);
    }

    event StartChallenge(address p, address c, bytes32 s, bytes32 e, uint256 par, uint to, bytes32 uniq);

    function make(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 par, uint to) public returns (bytes32) {
        bytes32 uniq = keccak256(task_id, p, c, s, e, par, to);
        Record storage r = records[uniq];
        r.task_id = task_id;
        r.prover = p;
        r.challenger = c;
        r.start_state = s;
        r.end_state = e;
        r.timeout = to;
        r.clock = block.number;
        r.next = r.prover;
        r.idx1 = 0;
        r.phase = 16;
        r.size = par;
        r.state = State.Started;
        /*
        r.steps = _steps;
        if (r.size > r.steps - 2) r.size = r.steps-2;
        r.proof.length = r.steps;
        r.proof[0] = s;
        r.proof[r.steps-1] = e;
        r.idx2 = r.steps-1;
        */
        r.state = State.Started;
        StartChallenge(p, c, s, e, r.size, to, uniq);
        blocked[task_id] = r.clock + r.timeout;
        return uniq;
    }

    function initialize(bytes32 id, bytes32[10] s_roots, uint[4] s_pointers, uint _steps,
                                    bytes32[10] e_roots, uint[4] e_pointers) public {
        Record storage r = records[id];
        require(msg.sender == r.next && r.state == State.Started);
        // check first state here
        require (r.start_state == judge.calcIOHash(s_roots));
        // then last one
        require (r.end_state == judge.calcIOHash(e_roots));

        // Now we can initialize
        r.steps = _steps;
        if (r.size > r.steps - 2) r.size = r.steps-2;
        r.idx2 = r.steps-1;
        r.proof.length = r.steps;
        r.proof[0] = judge.calcStateHash(s_roots, s_pointers);
        r.proof[r.steps-1] = judge.calcStateHash(e_roots, e_pointers);
        r.state = State.Running;
    }

    function getDescription(bytes32 id) public view returns (bytes32 init, uint steps, bytes32 last) {
        Record storage r = records[id];
        return (r.proof[0], r.steps, r.proof[r.steps-1]);
    }

    function getChallenger(bytes32 id) public view returns (address) {
       return records[id].challenger;
    }

    function getIndices(bytes32 id) public view returns (uint idx1, uint idx2) {
        Record storage r = records[id];
        return (r.idx1, r.idx2);
    }

    event StartFinalityChallenge(address p, address c, bytes32 s, bytes32 e, uint256 step, uint to, bytes32 uniq);

    // Solver thinks this is a final state, verifier disagrees
    // Solver has to post a proof that the next instruction is the "EXIT" opcode
    function makeFinality(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 _steps, uint to) public returns (bytes32) {
        bytes32 uniq = keccak256(task_id, p, c, s, e, _steps, to);
        Record storage r = records[uniq];
        r.task_id = task_id;
        r.prover = p;
        r.challenger = c;
        r.start_state = s;
        r.end_state = e;
        r.steps = _steps;
        r.timeout = to;
        r.clock = block.number;
        r.next = r.prover;
        r.phase = 20;
        r.size = 0;
        r.state = State.Finality;
        StartFinalityChallenge(p, c, s, e, _steps, to, uniq);
        blocked[task_id] = r.clock + r.timeout;
        return uniq;
    }

    function checkTimeout(bytes32 id) internal returns (bool) {
        Record storage r = records[id];
        if (r.state == State.Custom) return block.number >= r.judge.clock(r.sub_task) + r.timeout;
        return block.number >= r.clock + r.timeout && r.state != State.Finished;
   }

    function gameOver(bytes32 id) public returns (bool) {
        Record storage r = records[id];
        if (!checkTimeout(id)) return false;
        require(checkTimeout(id));
        if (r.next == r.prover) {
            r.winner = r.challenger;
            rejected[r.task_id] = true;
        }
        else {
            r.winner = r.prover;
            blocked[r.task_id] = 0;
        }
        WinnerSelected(id);
        r.state = State.Finished;
        return true;
    }

    function clock(bytes32 id) public returns (uint) {
        Record storage r = records[id];
        if (r.sub_task != 0) return r.judge.clock(r.sub_task);
        else return r.clock;
    }

    function isRejected(uint id) public view returns (bool) {
        return rejected[id];
    }

    function blockedTime(uint id) public view returns (uint) {
        return blocked[id] + 5;
    }

    function getIter(bytes32 id) internal view returns (uint it, uint i1, uint i2) {
        Record storage r = records[id];
        it = (r.idx2-r.idx1)/(r.size+1);
        i1 = r.idx1;
        i2 = r.idx2;
    }

    event Reported(bytes32 id, uint idx1, uint idx2, bytes32[] arr);

    function report(bytes32 id, uint i1, uint i2, bytes32[] arr) public returns (bool) {
        Record storage r = records[id];
        require(r.state == State.Running && arr.length == r.size && i1 == r.idx1 && i2 == r.idx2 &&
                msg.sender == r.prover && r.prover == r.next);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        uint iter = (r.idx2-r.idx1)/(r.size+1);
        for (uint i = 0; i < arr.length; i++) {
            r.proof[r.idx1+iter*(i+1)] = arr[i];
        }
        r.next = r.challenger;
        Reported(id, i1, i2, arr);
        return true;
    }

    function getStateAt(bytes32 id, uint loc) public view returns (bytes32) {
        return records[id].proof[loc];
    }

/*    function roundsTest(uint rounds, uint stuff) internal returns (uint it, uint i1, uint i2) {
        bytes32 id = testMake();
        Record storage r = records[id];
        for (uint i = 0; i < rounds; i++) {
            bytes32[] memory arr = new bytes32[](1);
            arr[0] = bytes32(0xffff);
            report(id, r.idx1, r.idx2, arr);
            query(id, r.idx1, r.idx2, stuff % 2);
            stuff = stuff/2;
        }
        return getIter(id);
    } */

    event Queried(bytes32 id, uint idx1, uint idx2);
    event NeedErrorPhases(bytes32 id, uint idx1);

    function query(bytes32 id, uint i1, uint i2, uint num) public {
        Record storage r = records[id];
        require(r.state == State.Running && num <= r.size && i1 == r.idx1 && i2 == r.idx2 &&
                msg.sender == r.challenger && r.challenger == r.next);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        uint iter = (r.idx2-r.idx1)/(r.size+1);
        r.idx1 = r.idx1+iter*num;
        // If last segment was selected, do not change last index
        if (num != r.size) r.idx2 = r.idx1+iter;
        if (r.size > r.idx2-r.idx1-1) r.size = r.idx2-r.idx1-1;
        // size eventually becomes zero here
        // check if they disagree on the last state being an error state
        if (r.size == 0 && r.idx2 == r.steps-1 && r.proof[r.idx2] == bytes32(0)) {
            r.next = r.challenger;
            // Challenger will have to post the phases
            NeedErrorPhases(id, r.idx1);
            r.state = State.NeedErrorPhases;
        }
        else {
            r.next = r.prover;
            Queried(id, r.idx1, r.idx2);
            if (r.size == 0) r.state = State.NeedPhases;
        }
    }

    function getStep(bytes32 id, uint idx) public view returns (bytes32) {
        Record storage r = records[id];
        return r.proof[idx];
    }

    event PostedPhases(bytes32 id, uint idx1, bytes32[13] arr);

    function postPhases(bytes32 id, uint i1, bytes32[13] arr) public {
        Record storage r = records[id];
        require(r.state == State.NeedPhases && msg.sender == r.prover && r.next == r.prover && r.idx1 == i1 &&
                r.proof[r.idx1] == arr[0] && r.proof[r.idx1+1] == arr[12] && arr[12] != bytes32(0));
        r.clock = block.number;
        r.state = State.PostedPhases;
        blocked[r.task_id] = r.clock + r.timeout;
        r.result = arr;
        r.next = r.challenger;
        PostedPhases(id, i1, arr);
    }

    event PostedErrorPhases(bytes32 id, uint idx1, bytes32[13] arr);

    function postErrorPhases(bytes32 id, uint i1, bytes32[13] arr) public {
        Record storage r = records[id];
        require(r.state == State.NeedErrorPhases && msg.sender == r.challenger && r.next == r.challenger && r.idx1 == i1 &&
                r.proof[r.idx1] == arr[0] && r.proof[r.idx1+1] == bytes32(0));
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        r.result = arr;
        r.next = r.prover;
        PostedErrorPhases(id, i1, arr);
        r.state = State.PostedErrorPhases;
    }

    function getResult(bytes32 id)  public view returns (bytes32[13]) {
        Record storage r = records[id];
        return r.result;
    }

    event SelectedPhase(bytes32 id, uint idx1, uint phase);

    function selectPhase(bytes32 id, uint i1, bytes32 st, uint q) public {
        Record storage r = records[id];
        require(r.state == State.PostedPhases && msg.sender == r.challenger && r.idx1 == i1 && r.result[q] == st &&
                r.next == r.challenger && q < 13);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        r.phase = q;
        SelectedPhase(id, i1, q);
        r.next = r.prover;
        r.state = State.SelectedPhase;
    }

    function getState(bytes32 id) public view returns (State) {
        return records[id].state;
    }

    function getPhase(bytes32 id) public view returns (uint) {
        return records[id].phase;
    }

    event SelectedErrorPhase(bytes32 id, uint idx1, uint phase);

    function selectErrorPhase(bytes32 id, uint i1, bytes32 st, uint q) public {
        Record storage r = records[id];
        require(r.state == State.PostedErrorPhases && msg.sender == r.prover && r.idx1 == i1 && r.result[q] == st &&
                r.next == r.prover && q < 13);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        r.phase = q;
        SelectedErrorPhase(id, i1, q);
        r.next = r.challenger;
        r.state = State.SelectedErrorPhase;
    }

    function getWinner(bytes32 id) public view returns (address) {
        return records[id].winner;
    }

    event WinnerSelected(bytes32 id);

    function callJudge(bytes32 id, uint i1, uint q,
                        bytes32[] proof, bytes32[] proof2,
                        bytes32 vm, bytes32 op, uint[4] regs,
                        bytes32[10] roots, uint[4] pointers) public {
        Record storage r = records[id];
        require(r.state == State.SelectedPhase && r.phase == q && msg.sender == r.prover && r.idx1 == i1 &&
                r.next == r.prover);

        // for custom judge, use another method
        /*
        uint alu_hint = (uint(op)/2**(8*3))&0xff;
        require (q != 5 || alu_hint != 0xff);
        */

        judge.judge(r.result, r.phase, proof, proof2, vm, op, regs, roots, pointers);
        WinnerSelected(id);
        r.winner = r.prover;
        blocked[r.task_id] = 0;
        r.state = State.Finished;
    }

    event SubGoal(bytes32 id, uint64 judge, bytes32 init_data, uint init_size, bytes32 ret_data, uint ret_size);

    function resolveCustom(bytes32 id) public returns (bool) {
        Record storage r = records[id];
        if (!r.judge.resolved(r.sub_task, r.ex_state, r.ex_size)) return false;
        WinnerSelected(id);
        r.winner = r.prover;
        blocked[r.task_id] = 0;
        r.state = State.Finished;
        return true;
    }

    // some register should have the input size?
    function callCustomJudge(bytes32 id, uint i1,
                        bytes32 op, uint[4] regs,
                        bytes32 custom_result, uint custom_size, bytes32[] custom_proof,
                        bytes32[10] roots, uint[4] pointers) public {

        Record storage r = records[id];
        require(r.state == State.SelectedPhase && r.phase == 6 && msg.sender == r.prover && r.idx1 == i1 &&
                r.next == r.prover);

        uint hint = (uint(op)/2**(8*5))&0xff;
        require (hint == 0x16);

        r.judge = judges[uint64(regs[3])];

        // uint256 init_size = regs[0] % 2 == 0 ? uint(custom_size_proof[0]) : uint(custom_size_proof[1]);
        bytes32 init_data = regs[0] % 2 == 0 ? custom_proof[0] : custom_proof[1];

        r.sub_task = r.judge.init(init_data, regs[1], regs[2], r.prover, r.challenger);
        r.ex_state = custom_result;
        r.ex_size = custom_size;
        judge.judgeCustom(r.result[5], r.result[6], custom_result, custom_size, op, regs, roots, pointers, custom_proof);
        r.state = State.Custom;

        SubGoal(id, uint64(regs[3]), init_data, regs[1], custom_result, custom_size);

        return;
    }

    // Challenger has claimed that the state is not final
    function callFinalityJudge(bytes32 id, uint i1,
                        bytes32[] proof, bytes32[] proof2,
                        bytes32[10] roots, uint[4] pointers) public {
        Record storage r = records[id];
        require(r.state == State.Finality && msg.sender == r.prover && r.idx1 == i1 &&
                r.next == r.prover);
        // bytes32 fetched_op = 0x0000000000000000000000000000000000000000040606060001000106000000;
        judge.judgeFinality(r.result, proof, proof2, roots, pointers);
        WinnerSelected(id);
        r.winner = r.prover;
        blocked[r.task_id] = 0;
        r.state = State.Finished;
    }

    function callErrorJudge(bytes32 id, uint i1, uint q,
                        bytes32[] proof, bytes32[] proof2,
                        bytes32 vm, bytes32 op, uint[4] regs,
                        bytes32[10] roots, uint[4] pointers) public {
        Record storage r = records[id];
        require(r.state == State.SelectedErrorPhase && r.phase == q && msg.sender == r.challenger && r.idx1 == i1 &&
                r.next == r.prover);
        judge.judge(r.result, r.phase, proof, proof2, vm, op, regs, roots, pointers);
        WinnerSelected(id);
        r.winner = r.challenger;
        rejected[r.task_id] = true;
    }

    function checkFileProof(bytes32 state, bytes32[10] roots, uint[4] pointers, bytes32[] proof, uint loc) public returns (bool) {
        return judge.checkFileProof(state, roots, pointers, proof, loc);
    }

    function checkProof(bytes32 hash, bytes32 root, bytes32[] proof, uint loc) public returns (bool) {
        return judge.checkProof(hash, root, proof, loc);
    }

    function calcStateHash(bytes32[10] roots, uint[4] pointers) public returns (bytes32) {
        return judge.calcStateHash(roots, pointers);
    }

}

pragma solidity ^0.4.16;

interface JudgeInterface {
    function judge(bytes32[13] res, uint q,
                        bytes32[] _proof, bytes32[] _proof2,
                        bytes32 vm_, bytes32 op, uint[4] regs,
                        bytes32[10] roots, uint[4] pointers) public returns (uint);
    function judgeFinality(bytes32[13] res, bytes32[] _proof, bytes32[] _proof2,
                        bytes32[10] roots, uint[4] pointers) public returns (uint);
    function judgeCustom(bytes32 state1, bytes32 state2, bytes32 ex_state, uint ex_reg, bytes32 op, uint[4] regs, bytes32[10] roots, uint[4] pointers, bytes32[] proof) public;

    function checkFileProof(bytes32 state, bytes32[10] roots, uint[4] pointers, bytes32[] proof, uint loc) public returns (bool);
    function checkProof(bytes32 hash, bytes32 root, bytes32[] proof, uint loc) public returns (bool);

    function calcStateHash(bytes32[10] roots, uint[4] pointers) public returns (bytes32);
    function calcIOHash(bytes32[10] roots) public returns (bytes32);
}

interface CustomJudge {
    // Initializes a new custom verification game
    function init(bytes32 state, uint state_size, uint r3, address solver, address verifier) public returns (bytes32);

    // Last time the task was updated
    function clock(bytes32 id) public returns (uint);

    // Check if has resolved into correct state: merkle root of output data and output size
    function resolved(bytes32 id, bytes32 state, uint size) public returns (bool);
}

contract Interactive2 {

    JudgeInterface judge;

    mapping (uint => uint) blocked;
    mapping (uint => bool) rejected;

    enum State {
        Started,
        Running, // First and last state have been set up ... but this will mean that the verification game is running now
        Finished, // Winner has been chosen
        NeedErrorPhases,
        NeedPhases,
        PostedErrorPhases,
        PostedPhases,
        SelectedErrorPhase,
        SelectedPhase,

        /* Special states for finality */
        Finality,
        Custom
    }

    struct Record {
        uint256 task_id;

        address prover;
        address challenger;

        bytes32 start_state; // actually initial code + input
        bytes32 end_state; // actually output

        // Maybe number of steps should be finished
        uint256 steps;

        address winner;
        address next;

        uint256 size;
        uint256 timeout;
        uint256 clock;

        uint256 idx1;
        uint256 idx2;

        uint256 phase;

        bytes32[] proof;
        bytes32[13] result;

        State state;

        //
        CustomJudge judge;
        bytes32 sub_task;
        bytes32 ex_state; // result from the custom judge
        uint ex_size;
    }

    function Interactive2(address addr) public {
        judge = JudgeInterface(addr);
    }

    mapping (bytes32 => Record) records;
    mapping (uint64 => CustomJudge) judges;

    // who should be able to
    function registerJudge(uint64 id, address addr) public {
        judges[id] = CustomJudge(addr);
    }

    event StartChallenge(address p, address c, bytes32 s, bytes32 e, uint256 par, uint to, bytes32 uniq);

    function make(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 par, uint to) public returns (bytes32) {
        bytes32 uniq = keccak256(task_id, p, c, s, e, par, to);
        Record storage r = records[uniq];
        r.task_id = task_id;
        r.prover = p;
        r.challenger = c;
        r.start_state = s;
        r.end_state = e;
        r.timeout = to;
        r.clock = block.number;
        r.next = r.prover;
        r.idx1 = 0;
        r.phase = 16;
        r.size = par;
        r.state = State.Started;
        /*
        r.steps = _steps;
        if (r.size > r.steps - 2) r.size = r.steps-2;
        r.proof.length = r.steps;
        r.proof[0] = s;
        r.proof[r.steps-1] = e;
        r.idx2 = r.steps-1;
        */
        r.state = State.Started;
        StartChallenge(p, c, s, e, r.size, to, uniq);
        blocked[task_id] = r.clock + r.timeout;
        return uniq;
    }

    function initialize(bytes32 id, bytes32[10] s_roots, uint[4] s_pointers, uint _steps,
                                    bytes32[10] e_roots, uint[4] e_pointers) public {
        Record storage r = records[id];
        require(msg.sender == r.next && r.state == State.Started);
        // check first state here
        require (r.start_state == judge.calcIOHash(s_roots));
        // then last one
        require (r.end_state == judge.calcIOHash(e_roots));

        // Now we can initialize
        r.steps = _steps;
        if (r.size > r.steps - 2) r.size = r.steps-2;
        r.idx2 = r.steps-1;
        r.proof.length = r.steps;
        r.proof[0] = judge.calcStateHash(s_roots, s_pointers);
        r.proof[r.steps-1] = judge.calcStateHash(e_roots, e_pointers);
        r.state = State.Running;
    }

    function getDescription(bytes32 id) public view returns (bytes32 init, uint steps, bytes32 last) {
        Record storage r = records[id];
        return (r.proof[0], r.steps, r.proof[r.steps-1]);
    }

    function getChallenger(bytes32 id) public view returns (address) {
       return records[id].challenger;
    }

    function getIndices(bytes32 id) public view returns (uint idx1, uint idx2) {
        Record storage r = records[id];
        return (r.idx1, r.idx2);
    }

    event StartFinalityChallenge(address p, address c, bytes32 s, bytes32 e, uint256 step, uint to, bytes32 uniq);

    // Solver thinks this is a final state, verifier disagrees
    // Solver has to post a proof that the next instruction is the "EXIT" opcode
    function makeFinality(uint task_id, address p, address c, bytes32 s, bytes32 e, uint256 _steps, uint to) public returns (bytes32) {
        bytes32 uniq = keccak256(task_id, p, c, s, e, _steps, to);
        Record storage r = records[uniq];
        r.task_id = task_id;
        r.prover = p;
        r.challenger = c;
        r.start_state = s;
        r.end_state = e;
        r.steps = _steps;
        r.timeout = to;
        r.clock = block.number;
        r.next = r.prover;
        r.phase = 20;
        r.size = 0;
        r.state = State.Finality;
        StartFinalityChallenge(p, c, s, e, _steps, to, uniq);
        blocked[task_id] = r.clock + r.timeout;
        return uniq;
    }

    function checkTimeout(bytes32 id) internal returns (bool) {
        Record storage r = records[id];
        if (r.state == State.Custom) return block.number >= r.judge.clock(r.sub_task) + r.timeout;
        return block.number >= r.clock + r.timeout && r.state != State.Finished;
   }

    function gameOver(bytes32 id) public returns (bool) {
        Record storage r = records[id];
        if (!checkTimeout(id)) return false;
        require(checkTimeout(id));
        if (r.next == r.prover) {
            r.winner = r.challenger;
            rejected[r.task_id] = true;
        }
        else {
            r.winner = r.prover;
            blocked[r.task_id] = 0;
        }
        WinnerSelected(id);
        r.state = State.Finished;
        return true;
    }

    function clock(bytes32 id) public returns (uint) {
        Record storage r = records[id];
        if (r.sub_task != 0) return r.judge.clock(r.sub_task);
        else return r.clock;
    }

    function isRejected(uint id) public view returns (bool) {
        return rejected[id];
    }

    function blockedTime(uint id) public view returns (uint) {
        return blocked[id] + 5;
    }

    function getIter(bytes32 id) internal view returns (uint it, uint i1, uint i2) {
        Record storage r = records[id];
        it = (r.idx2-r.idx1)/(r.size+1);
        i1 = r.idx1;
        i2 = r.idx2;
    }

    event Reported(bytes32 id, uint idx1, uint idx2, bytes32[] arr);

    function report(bytes32 id, uint i1, uint i2, bytes32[] arr) public returns (bool) {
        Record storage r = records[id];
        require(r.state == State.Running && arr.length == r.size && i1 == r.idx1 && i2 == r.idx2 &&
                msg.sender == r.prover && r.prover == r.next);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        uint iter = (r.idx2-r.idx1)/(r.size+1);
        for (uint i = 0; i < arr.length; i++) {
            r.proof[r.idx1+iter*(i+1)] = arr[i];
        }
        r.next = r.challenger;
        Reported(id, i1, i2, arr);
        return true;
    }

    function getStateAt(bytes32 id, uint loc) public view returns (bytes32) {
        return records[id].proof[loc];
    }

/*    function roundsTest(uint rounds, uint stuff) internal returns (uint it, uint i1, uint i2) {
        bytes32 id = testMake();
        Record storage r = records[id];
        for (uint i = 0; i < rounds; i++) {
            bytes32[] memory arr = new bytes32[](1);
            arr[0] = bytes32(0xffff);
            report(id, r.idx1, r.idx2, arr);
            query(id, r.idx1, r.idx2, stuff % 2);
            stuff = stuff/2;
        }
        return getIter(id);
    } */

    event Queried(bytes32 id, uint idx1, uint idx2);
    event NeedErrorPhases(bytes32 id, uint idx1);

    function query(bytes32 id, uint i1, uint i2, uint num) public {
        Record storage r = records[id];
        require(r.state == State.Running && num <= r.size && i1 == r.idx1 && i2 == r.idx2 &&
                msg.sender == r.challenger && r.challenger == r.next);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        uint iter = (r.idx2-r.idx1)/(r.size+1);
        r.idx1 = r.idx1+iter*num;
        // If last segment was selected, do not change last index
        if (num != r.size) r.idx2 = r.idx1+iter;
        if (r.size > r.idx2-r.idx1-1) r.size = r.idx2-r.idx1-1;
        // size eventually becomes zero here
        // check if they disagree on the last state being an error state
        if (r.size == 0 && r.idx2 == r.steps-1 && r.proof[r.idx2] == bytes32(0)) {
            r.next = r.challenger;
            // Challenger will have to post the phases
            NeedErrorPhases(id, r.idx1);
            r.state = State.NeedErrorPhases;
        }
        else {
            r.next = r.prover;
            Queried(id, r.idx1, r.idx2);
            if (r.size == 0) r.state = State.NeedPhases;
        }
    }

    function getStep(bytes32 id, uint idx) public view returns (bytes32) {
        Record storage r = records[id];
        return r.proof[idx];
    }

    event PostedPhases(bytes32 id, uint idx1, bytes32[13] arr);

    function postPhases(bytes32 id, uint i1, bytes32[13] arr) public {
        Record storage r = records[id];
        require(r.state == State.NeedPhases && msg.sender == r.prover && r.next == r.prover && r.idx1 == i1 &&
                r.proof[r.idx1] == arr[0] && r.proof[r.idx1+1] == arr[12] && arr[12] != bytes32(0));
        r.clock = block.number;
        r.state = State.PostedPhases;
        blocked[r.task_id] = r.clock + r.timeout;
        r.result = arr;
        r.next = r.challenger;
        PostedPhases(id, i1, arr);
    }

    event PostedErrorPhases(bytes32 id, uint idx1, bytes32[13] arr);

    function postErrorPhases(bytes32 id, uint i1, bytes32[13] arr) public {
        Record storage r = records[id];
        require(r.state == State.NeedErrorPhases && msg.sender == r.challenger && r.next == r.challenger && r.idx1 == i1 &&
                r.proof[r.idx1] == arr[0] && r.proof[r.idx1+1] == bytes32(0));
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        r.result = arr;
        r.next = r.prover;
        PostedErrorPhases(id, i1, arr);
        r.state = State.PostedErrorPhases;
    }

    function getResult(bytes32 id)  public view returns (bytes32[13]) {
        Record storage r = records[id];
        return r.result;
    }

    event SelectedPhase(bytes32 id, uint idx1, uint phase);

    function selectPhase(bytes32 id, uint i1, bytes32 st, uint q) public {
        Record storage r = records[id];
        require(r.state == State.PostedPhases && msg.sender == r.challenger && r.idx1 == i1 && r.result[q] == st &&
                r.next == r.challenger && q < 13);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        r.phase = q;
        SelectedPhase(id, i1, q);
        r.next = r.prover;
        r.state = State.SelectedPhase;
    }

    function getState(bytes32 id) public view returns (State) {
        return records[id].state;
    }

    function getPhase(bytes32 id) public view returns (uint) {
        return records[id].phase;
    }

    event SelectedErrorPhase(bytes32 id, uint idx1, uint phase);

    function selectErrorPhase(bytes32 id, uint i1, bytes32 st, uint q) public {
        Record storage r = records[id];
        require(r.state == State.PostedErrorPhases && msg.sender == r.prover && r.idx1 == i1 && r.result[q] == st &&
                r.next == r.prover && q < 13);
        r.clock = block.number;
        blocked[r.task_id] = r.clock + r.timeout;
        r.phase = q;
        SelectedErrorPhase(id, i1, q);
        r.next = r.challenger;
        r.state = State.SelectedErrorPhase;
    }

    function getWinner(bytes32 id) public view returns (address) {
        return records[id].winner;
    }

    event WinnerSelected(bytes32 id);

    function resolveCustom(bytes32 id) public {
        Record storage r = records[id];
        require (r.judge.resolved(r.sub_task, r.ex_state, r.ex_size));
        WinnerSelected(id);
        r.winner = r.prover;
        blocked[r.task_id] = 0;
        r.state = State.Finished;
    }

    function callJudge(bytes32 id, uint i1, uint q,
                        bytes32[] proof, bytes32[] proof2,
                        bytes32 vm, bytes32 op, uint[4] regs,
                        bytes32[10] roots, uint[4] pointers) public {
        Record storage r = records[id];
        require(r.state == State.SelectedPhase && r.phase == q && msg.sender == r.prover && r.idx1 == i1 &&
                r.next == r.prover);

        // for custom judge, use another method
        /*
        uint alu_hint = (uint(op)/2**(8*3))&0xff;
        require (q != 5 || alu_hint != 0xff);
        */

        judge.judge(r.result, r.phase, proof, proof2, vm, op, regs, roots, pointers);
        WinnerSelected(id);
        r.winner = r.prover;
        blocked[r.task_id] = 0;
        r.state = State.Finished;
    }

    event SubGoal(bytes32 id, uint64 judge, bytes32 init_data, uint init_size, bytes32 ret_data, uint ret_size);

    // some register should have the input size?
    function callCustomJudge(bytes32 id, uint i1,
                        bytes32 op, uint[4] regs,
                        bytes32 custom_result, uint custom_size, bytes32[] custom_proof,
                        bytes32[10] roots, uint[4] pointers) public {

        Record storage r = records[id];
        require(r.state == State.SelectedPhase && r.phase == 6 && msg.sender == r.prover && r.idx1 == i1 &&
                r.next == r.prover);

        uint hint = (uint(op)/2**(8*5))&0xff;
        require (hint == 0x16);

        r.judge = judges[uint64(regs[3])];

        // uint256 init_size = regs[0] % 2 == 0 ? uint(custom_size_proof[0]) : uint(custom_size_proof[1]);
        bytes32 init_data = regs[0] % 2 == 0 ? custom_proof[0] : custom_proof[1];

        r.sub_task = r.judge.init(init_data, regs[1], regs[2], r.prover, r.challenger);
        r.ex_state = custom_result;
        r.ex_size = custom_size;
        judge.judgeCustom(r.result[5], r.result[6], custom_result, custom_size, op, regs, roots, pointers, custom_proof);
        r.state = State.Custom;

        SubGoal(id, uint64(regs[3]), init_data, regs[1], custom_result, custom_size);

        return;
    }

    // Challenger has claimed that the state is not final
    function callFinalityJudge(bytes32 id, uint i1,
                        bytes32[] proof, bytes32[] proof2,
                        bytes32[10] roots, uint[4] pointers) public {
        Record storage r = records[id];
        require(r.state == State.Finality && msg.sender == r.prover && r.idx1 == i1 &&
                r.next == r.prover);
        // bytes32 fetched_op = 0x0000000000000000000000000000000000000000040606060001000106000000;
        judge.judgeFinality(r.result, proof, proof2, roots, pointers);
        WinnerSelected(id);
        r.winner = r.prover;
        blocked[r.task_id] = 0;
        r.state = State.Finished;
    }

    function callErrorJudge(bytes32 id, uint i1, uint q,
                        bytes32[] proof, bytes32[] proof2,
                        bytes32 vm, bytes32 op, uint[4] regs,
                        bytes32[10] roots, uint[4] pointers) public {
        Record storage r = records[id];
        require(r.state == State.SelectedErrorPhase && r.phase == q && msg.sender == r.challenger && r.idx1 == i1 &&
                r.next == r.prover);
        judge.judge(r.result, r.phase, proof, proof2, vm, op, regs, roots, pointers);
        WinnerSelected(id);
        r.winner = r.challenger;
        rejected[r.task_id] = true;
    }

    function checkFileProof(bytes32 state, bytes32[10] roots, uint[4] pointers, bytes32[] proof, uint loc) public returns (bool) {
        return judge.checkFileProof(state, roots, pointers, proof, loc);
    }

    function checkProof(bytes32 hash, bytes32 root, bytes32[] proof, uint loc) public returns (bool) {
        return judge.checkProof(hash, root, proof, loc);
    }

    function calcStateHash(bytes32[10] roots, uint[4] pointers) public returns (bytes32) {
        return judge.calcStateHash(roots, pointers);
    }

}


add contract

add contract

/* Part of this contract is from the solidity documentation
TODO: Set a license.
*/

pragma solidity ^0.4.9;

/// @title Fund for donations.
contract AbieFund {

    uint membershipFee = 0.1 ether;
    uint nbMembers;
    uint registrationTime = 1 years;
    uint[2] voteLength = [1 weeks, 1 weeks];

    event Donated(address donor, uint amount);

    enum ProposalType {AddMember,FundProject} // Different types of proposals.
    enum VoteType {Abstain,Yes,No} // Different value of a vote.

    struct Proposal
    {
        bytes32 name;       // short name (up to 32 bytes).
        uint voteYes;     // number of YES votes.
        uint voteAbstain;     // number of abstention. Number of No can be deduced.
        address recipient;     // address the funds will be sent.
        uint value;         // quantity of wei to be sent.
        bytes32 data;       // data of the transaction.
        ProposalType proposalType;  // type of the proposal.
        uint endDate; // when the vote will be closed.
        mapping (address => VoteType) vote; // vote of the party.
        mapping (address => bool) voteCounted; // has the vote been counted yet?
    }

    // Is also a node list.
    struct Member
    {
        uint registration;  // date of registration, if 0 the member does not exist.
        address[2] delegate; // delegate[proposalType] gives the delegate for the type.
        address prev;
        address succ;
    }

    mapping (address => Member) public members;

    // Double chained list.
    struct DoubleChainedList
    {
        address first;
        address last;
    }

    // Chain containing all members to iterate on.
    DoubleChainedList memberList;

    Proposal[] public proposals;

    /// Require at least price to be paid.
    modifier costs(uint price) {
        if (msg.value<price)
            throw;
        _;
    }

    /// Require the caller to be a member.
    modifier isMember() {
        if (members[msg.sender].registration==0) // Not a member.
            throw;
        if (members[msg.sender].registration+registrationTime<now) // Has expired.
            throw;
        _;
    }

/*
function insertEnd(List list, Node newNode)
     if list.lastNode == null
         insertBeginning(list, newNode)
     else
         insertAfter(list, list.lastNode, newNode)
*/

    /// @param initialMembers First members of the organization.
    function AbieFund(address[] initialMembers) {
        for (uint i;i<initialMembers.length;++i){
            Member member=members[initialMembers[i]];
            member.registration=now;
            if (i==0) { // initialize the list with the first member
                memberList.first=initialMembers[0];
                memberList.last=initialMembers[0];
            } else { // add members
                addMember(initialMembers[i]);
            }
        }
        nbMembers=initialMembers.length;
    }

    // Add the member m to the member list.
    // Assume that there is at least 1 member registrated.
    function addMember(address m) private {
        members[memberList.last].succ=m;
        members[m].prev=memberList.last;
        memberList.last=m;
    }

    /** Choose a delegate.
      * @param proposalType 0 for AddMember, 1 for FundProject.
      * @param target account to delegate to.
      */
    function setDelegate(uint8 proposalType, address target)
    {
        members[msg.sender].delegate[proposalType] = target;
    }

    /// Receive funds.
    function () payable {
        Donated(msg.sender, msg.value);
    }

    /// Ask membership of the fund.
    function askMembership () payable costs(membershipFee) {
        Donated(msg.sender,msg.value); // Register the donation.

        // Create a proposal to add the member.
        proposals.push(Proposal({
        name: 0x0,
        voteYes: 0,
        voteAbstain: 0,
        recipient: msg.sender,
        value: 0x0,
        data: 0x0,
        proposalType: ProposalType.AddMember,
        endDate: now + voteLength[uint256(ProposalType.AddMember)]
        }));
    }

    /** Vote for a proposal.
     *  @param proposalID ID of the proposal to count votes from.
     *  @param voteType Yes or No.
     */
    function vote (uint proposalID, VoteType voteType) isMember {
        Proposal proposal = proposals[proposalID];
        if (proposal.vote[msg.sender] != VoteType.Abstain) // Has already voted.
            throw;
        if (proposal.endDate < now) // Vote is over.
            throw;

        proposals[proposalID].vote[msg.sender] = voteType;
    }

    /** Count all the votes of a proposal.
     *  @param proposalID ID of the proposal to count votes from.
     */
    function countAllVotes (uint proposalID) {
        countVotes (proposalID, memberList.first, 0);
    }

    /** Count the votes from start to end.
     *  This function is necessary to count in multiple times if counting reach gas limit.
     *  We just count the number of Yes and Abstention, so we will deduce the number of No.
     *  @param proposalID ID of the proposal to count votes from.
     *  @param start First member to count from.
     *  @param end   Count votes of all members before this one (end is not included), put to 0 to count till the end.
     */
    function countVotes (uint proposalID, address start, address end) {
        Proposal proposal = proposals[proposalID];

        while (start != end) {
            Member member=members[start];
            if (proposal.voteCounted[start]==false) { // Verify the vote has not been counted yet.
                proposal.voteCounted[start]=true; // The vote will be counted.

                address delegate=start;
                // Seach the final vote.
                while (true){
                    VoteType vote=proposal.vote[delegate];
                    if (vote==VoteType.Abstain) { // Look at the delegate
                        delegate=members[delegate].delegate[uint(proposal.proposalType)]; // Find the delegate.
                        if (delegate==start || delegate==0) { // Back to the start of the loop or failed to name a delegate.
                           proposal.voteAbstain+=1;
                           break;
                        }
                    }
                    if (vote==VoteType.Yes) {
                        proposal.voteYes+=1;
                        break;
                    }
                    // Else voted No, so we don't count.
                }

            }
            start=member.succ; // In next iteration start from the next node.

            // TODO: Delete the members if they are expired.
        }

    }

    /// CONSTANTS ///

    /** Return the delegate.
     *  @param member member to get the delegate from.
     *  @param proposalType 0 for AddMember, 1 for FundProject.
     */
    function getDelegate(address member, uint8 proposalType) constant returns (address){
        return members[member].delegate[proposalType];
    }

    /** Return true if the proposal is validated, false otherwise.
     *  @param proposalID ID of the proposal to count votes from.
     */
    function isValidated(uint proposalID) returns (bool) {
        Proposal proposal = proposals[proposalID];
        if (proposal.endDate > now)
            return false;

        // Deduce the number of votes No by discounting the number of abstentions and votes Yes.
        uint voteNo=nbMembers;
        if (voteNo-proposal.voteYes>voteNo) // Overflow somewhere.
            return false;
        else
            voteNo-=proposal.voteYes;

        if (voteNo-proposal.voteAbstain>voteNo) // Overflow somewhere.
            return false;
        else
            voteNo-=proposal.voteAbstain;

        return (proposal.voteYes>voteNo);
    }

}

/* Part of this contract is from the solidity documentation
TODO: Set a license.
*/

pragma solidity ^0.4.8;

/// @title Voting with delegation.
contract AbieFund {

    uint membershipFee = 0.1 ether;
    uint nbMembers;
    uint registrationTime = 1 years;

    uint8 public test = 8; // temp for test purpose

    event Donated(address donor, uint amount);

    enum ProposalType {AddMember,FundProject} // Different types of proposals.
    enum VoteType {Abstain,Yes,No} // Different value of a vote.

    struct Proposal
    {
        bytes32 name;       // short name (up to 32 bytes).
        uint voteYes;     // number of YES votes.
        uint voteAbstain;     // number of abstention. Number of No can be deduced.
        address recipient;     // address the funds will be sent.
        uint value;         // quantity of wei to be sent.
        bytes32 data;       // data of the transaction.
        ProposalType proposalType;  // type of the proposal.
        mapping (address => VoteType) vote; // vote of the party.
        mapping (address => bool) voteCounted;
    }

    struct Member
    {
        uint registration;  // date of registration, if 0 the member does not exist.
        address[2] delegate; // delegate[proposalType] gives the delegate for the type.
    }

    mapping (address => Member) public members;

    Proposal[] public proposals;

    /// Require at least price to be paid.
    modifier costs(uint price) {
        if (msg.value<price)
            throw;
        _;
    }

    /// Require the caller to be a member.
    modifier isMember() {
        if (members[msg.sender].registration==0) // Not a member.
            throw;
        if (members[msg.sender].registration+registrationTime<now) // Has expired.
            throw;
        _;
    }

    /// @param initialMembers First members of the organization.
    function AbieFund(address[] initialMembers) {
        for (uint i;i<initialMembers.length;++i)
            members[initialMembers[i]].registration=now;
        nbMembers=initialMembers.length;
    }

    /** Choose a delegate.
      * @param proposalType 0 for AddMember, 1 for FundProject.
      * @param target account to delegate to.
      */
    function setDelegate(uint8 proposalType, address target)
    {
        members[msg.sender].delegate[proposalType] = target;
    }

    /// Receive funds.
    function () payable {
        Donated(msg.sender, msg.value);
    }

    function askMembership () payable costs(membershipFee) {
        Donated(msg.sender,msg.value); // Register the donation.

        // Create a proposal to add the member.
        proposals.push(Proposal({
        name: 0x0,
        voteYes: 0,
        voteAbstain: 0,
        recipient: msg.sender,
        value: 0x0,
        data: 0x0,
        proposalType: ProposalType.AddMember
        }));
    }

    function vote (uint proposal, VoteType voteType) isMember {
        // TODO
    }

    /// GETTERS ///

    /** Return the delegate.
     *  @param member member to get the delegate from.
     *  @param proposalType 0 for AddMember, 1 for FundProject.
     */
    function getDelegate(address member, uint8 proposalType) constant returns (address){
        return members[member].delegate[proposalType];
    }

}


fix bugs in month and day calcs

fix bugs in month and day calcs

contract DateTime {
        /*
         *  Date and Time utilities for ethereum contracts
         *
         *  address: 0x1a6184cd4c5bea62b0116de7962ee7315b7bcbce
         */
        struct DateTime {
                uint16 year;
                uint8 month;
                uint8 day;
                uint8 hour;
                uint8 minute;
                uint8 second;
                uint8 weekday;
        }

        uint constant DAY_IN_SECONDS = 86400;
        uint constant YEAR_IN_SECONDS = 31536000;
        uint constant LEAP_YEAR_IN_SECONDS = 31622400;

        uint constant HOUR_IN_SECONDS = 3600;
        uint constant MINUTE_IN_SECONDS = 60;

        uint16 constant ORIGIN_YEAR = 1970;

        function isLeapYear(uint16 year) constant returns (bool) {
                if (year % 4 != 0) {
                        return false;
                }
                if (year % 100 != 0) {
                        return true;
                }
                if (year % 400 != 0) {
                        return false;
                }
                return true;
        }

        function leapYearsBefore(uint year) constant returns (uint) {
                year -= 1;
                return year / 4 - year / 100 + year / 400;
        }

        function getDaysInMonth(uint8 month, uint16 year) constant returns (uint8) {
                if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
                        return 31;
                }
                else if (month == 4 || month == 6 || month == 9 || month == 11) {
                        return 30;
                }
                else if (isLeapYear(year)) {
                        return 29;
                }
                else {
                        return 28;
                }
        }

        function parseTimestamp(uint timestamp) internal returns (DateTime dt) {
                uint secondsAccountedFor = 0;
                uint buf;
                uint8 i;

                // Year
                dt.year = getYear(timestamp);
                buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR);

                secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;
                secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf);

                // Month
                uint secondsInMonth;
                for (i = 1; i <= 12; i++) {
                        secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year);
                        if (secondsInMonth + secondsAccountedFor > timestamp) {
                                dt.month = i;
                                break;
                        }
                        secondsAccountedFor += secondsInMonth;
                }

                // Day
                for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) {
                        if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) {
                                dt.day = i;
                                break;
                        }
                        secondsAccountedFor += DAY_IN_SECONDS;
                }

                // Hour
                dt.hour = getHour(timestamp);

                // Minute
                dt.minute = getMinute(timestamp);

                // Second
                dt.second = getSecond(timestamp);

                // Day of week.
                dt.weekday = getWeekday(timestamp);
        }

        function getYear(uint timestamp) constant returns (uint16) {
                uint secondsAccountedFor = 0;
                uint16 year;
                uint numLeapYears;

                // Year
                year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS);
                numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);

                secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears;
                secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears);

                while (secondsAccountedFor > timestamp) {
                        if (isLeapYear(uint16(year - 1))) {
                                secondsAccountedFor -= LEAP_YEAR_IN_SECONDS;
                        }
                        else {
                                secondsAccountedFor -= YEAR_IN_SECONDS;
                        }
                        year -= 1;
                }
                return year;
        }

        function getMonth(uint timestamp) constant returns (uint8) {
                return parseTimestamp(timestamp).month;
        }

        function getDay(uint timestamp) constant returns (uint8) {
                return parseTimestamp(timestamp).day;
        }

        function getHour(uint timestamp) constant returns (uint8) {
                return uint8((timestamp / 60 / 60) % 24);
        }

        function getMinute(uint timestamp) constant returns (uint8) {
                return uint8((timestamp / 60) % 60);
        }

        function getSecond(uint timestamp) constant returns (uint8) {
                return uint8(timestamp % 60);
        }

        function getWeekday(uint timestamp) constant returns (uint8) {
                return uint8((timestamp / DAY_IN_SECONDS + 4) % 7);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day) constant returns (uint timestamp) {
                return toTimestamp(year, month, day, 0, 0, 0);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) constant returns (uint timestamp) {
                return toTimestamp(year, month, day, hour, 0, 0);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) constant returns (uint timestamp) {
                return toTimestamp(year, month, day, hour, minute, 0);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) constant returns (uint timestamp) {
                uint16 i;

                // Year
                for (i = ORIGIN_YEAR; i < year; i++) {
                        if (isLeapYear(i)) {
                                timestamp += LEAP_YEAR_IN_SECONDS;
                        }
                        else {
                                timestamp += YEAR_IN_SECONDS;
                        }
                }

                // Month
                uint8[12] monthDayCounts;
                monthDayCounts[0] = 31;
                if (isLeapYear(year)) {
                        monthDayCounts[1] = 29;
                }
                else {
                        monthDayCounts[1] = 28;
                }
                monthDayCounts[2] = 31;
                monthDayCounts[3] = 30;
                monthDayCounts[4] = 31;
                monthDayCounts[5] = 30;
                monthDayCounts[6] = 31;
                monthDayCounts[7] = 31;
                monthDayCounts[8] = 30;
                monthDayCounts[9] = 31;
                monthDayCounts[10] = 30;
                monthDayCounts[11] = 31;

                for (i = 1; i < month; i++) {
                        timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1];
                }

                // Day
                timestamp += DAY_IN_SECONDS * (day - 1);

                // Hour
                timestamp += HOUR_IN_SECONDS * (hour);

                // Minute
                timestamp += MINUTE_IN_SECONDS * (minute);

                // Second
                timestamp += second;

                return timestamp;
        }

        function __throw() {
                uint[] arst;
                arst[1];
        }
}

contract DateTime {
        /*
         *  Date and Time utilities for ethereum contracts
         *
         *  address: 0x1a6184cd4c5bea62b0116de7962ee7315b7bcbce
         */
        struct DateTime {
                uint16 year;
                uint8 month;
                uint8 day;
                uint8 hour;
                uint8 minute;
                uint8 second;
                uint8 weekday;
        }

        uint constant DAY_IN_SECONDS = 86400;
        uint constant YEAR_IN_SECONDS = 31536000;
        uint constant LEAP_YEAR_IN_SECONDS = 31622400;

        uint constant HOUR_IN_SECONDS = 3600;
        uint constant MINUTE_IN_SECONDS = 60;

        uint16 constant ORIGIN_YEAR = 1970;

        function isLeapYear(uint16 year) constant returns (bool) {
                if (year % 4 != 0) {
                        return false;
                }
                if (year % 100 != 0) {
                        return true;
                }
                if (year % 400 != 0) {
                        return false;
                }
                return true;
        }

        function leapYearsBefore(uint year) constant returns (uint) {
                year -= 1;
                return year / 4 - year / 100 + year / 400;
        }

        function getDaysInMonth(uint8 month, uint16 year) constant returns (uint8) {
                if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
                        return 31;
                }
                else if (month == 4 || month == 6 || month == 9 || month == 11) {
                        return 30;
                }
                else if (isLeapYear(year)) {
                        return 29;
                }
                else {
                        return 28;
                }
        }

        function parseTimestamp(uint timestamp) internal returns (DateTime dt) {
                uint secondsAccountedFor = 0;
                uint buf;
                uint8 i;

                // Year
                dt.year = getYear(timestamp);
                buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR);

                secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf;
                secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf);

                // Month
                uint secondsInMonth;
                for (i = 1; i <= 12; i++) {
                        secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year);
                        if (secondsInMonth + secondsAccountedFor > timestamp) {
                                dt.month = i + 1;
                                break;
                        }
                        secondsAccountedFor += secondsInMonth;
                }

                // Day
                for (i = 1; i < getDaysInMonth(dt.month, dt.year); i++) {
                        if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) {
                                dt.day = i + 1;
                                break;
                        }
                        secondsAccountedFor += DAY_IN_SECONDS;
                }

                // Hour
                dt.hour = getHour(timestamp);

                // Minute
                dt.minute = getMinute(timestamp);

                // Second
                dt.second = getSecond(timestamp);

                // Day of week.
                dt.weekday = getWeekday(timestamp);
        }

        function getYear(uint timestamp) constant returns (uint16) {
                uint secondsAccountedFor = 0;
                uint16 year;
                uint numLeapYears;

                // Year
                year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS);
                numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR);

                secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears;
                secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears);

                while (secondsAccountedFor > timestamp) {
                        if (isLeapYear(uint16(year - 1))) {
                                secondsAccountedFor -= LEAP_YEAR_IN_SECONDS;
                        }
                        else {
                                secondsAccountedFor -= YEAR_IN_SECONDS;
                        }
                        year -= 1;
                }
                return year;
        }

        function getMonth(uint timestamp) constant returns (uint8) {
                return parseTimestamp(timestamp).month;
        }

        function getDay(uint timestamp) constant returns (uint8) {
                return parseTimestamp(timestamp).day;
        }

        function getHour(uint timestamp) constant returns (uint8) {
                return uint8((timestamp / 60 / 60) % 24);
        }

        function getMinute(uint timestamp) constant returns (uint8) {
                return uint8((timestamp / 60) % 60);
        }

        function getSecond(uint timestamp) constant returns (uint8) {
                return uint8(timestamp % 60);
        }

        function getWeekday(uint timestamp) constant returns (uint8) {
                return uint8((timestamp / DAY_IN_SECONDS + 4) % 7);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day) constant returns (uint timestamp) {
                return toTimestamp(year, month, day, 0, 0, 0);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) constant returns (uint timestamp) {
                return toTimestamp(year, month, day, hour, 0, 0);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) constant returns (uint timestamp) {
                return toTimestamp(year, month, day, hour, minute, 0);
        }

        function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) constant returns (uint timestamp) {
                uint16 i;

                // Year
                for (i = ORIGIN_YEAR; i < year; i++) {
                        if (isLeapYear(i)) {
                                timestamp += LEAP_YEAR_IN_SECONDS;
                        }
                        else {
                                timestamp += YEAR_IN_SECONDS;
                        }
                }

                // Month
                uint8[12] monthDayCounts;
                monthDayCounts[0] = 31;
                if (isLeapYear(year)) {
                        monthDayCounts[1] = 29;
                }
                else {
                        monthDayCounts[1] = 28;
                }
                monthDayCounts[2] = 31;
                monthDayCounts[3] = 30;
                monthDayCounts[4] = 31;
                monthDayCounts[5] = 30;
                monthDayCounts[6] = 31;
                monthDayCounts[7] = 31;
                monthDayCounts[8] = 30;
                monthDayCounts[9] = 31;
                monthDayCounts[10] = 30;
                monthDayCounts[11] = 31;

                for (i = 1; i < month; i++) {
                        timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1];
                }

                // Day
                timestamp += DAY_IN_SECONDS * (day - 1);

                // Hour
                timestamp += HOUR_IN_SECONDS * (hour);

                // Minute
                timestamp += MINUTE_IN_SECONDS * (minute);

                // Second
                timestamp += second;

                return timestamp;
        }

        function __throw() {
                uint[] arst;
                arst[1];
        }
}


add view prop to Registry method

add view prop to Registry method

pragma solidity ^0.4.17;

import "./Controlled.sol";

contract Registry is Controlled {

    struct User {
        address                     owner;
        mapping(uint => uint)       values;
    }

    mapping(bytes20 => User)    public usernameToUser;
    mapping(address => bytes20) public ownerToUsername;

    bytes20[]                   public userValueNames;

    event Added(bytes20 username);
    event Removed(bytes20 username);

    function Registry() {
        addUserValueName("TOKEN_AGE_START");
        addUserValueName("DAY_TRANSFERS_START");
        addUserValueName("DAY_TOTAL");
    }

    function add(bytes20 _username, address _owner) public onlyController {
        usernameToUser[_username] = User({owner: _owner});
        ownerToUsername[_owner] = _username;
        Added(_username);
    }

    function remove(bytes20 _username) public onlyController {
        delete ownerToUsername[usernameToUser[_username].owner];
        delete usernameToUser[_username];
        Removed(_username);
    }

    function addUserValueName(bytes20 _valueName) public onlyController {
        userValueNames.push(_valueName);
    }

    function getOwner(bytes20 _username) public view returns(address owner) {
        owner = usernameToUser[_username].owner;
    }

    function getUserValue(bytes20 _username, uint _valueIdx) public returns(uint value) {
        value = usernameToUser[_username].values[_valueIdx];
    }

    function setUserValue(bytes20 _username, uint _valueIdx, uint _value) public onlyController {
        usernameToUser[_username].values[_valueIdx] = _value;
    }

}

pragma solidity ^0.4.17;

import "./Controlled.sol";

contract Registry is Controlled {

    struct User {
        address                     owner;
        mapping(uint => uint)       values;
    }

    mapping(bytes20 => User)    public usernameToUser;
    mapping(address => bytes20) public ownerToUsername;

    bytes20[]                   public userValueNames;

    event Added(bytes20 username);
    event Removed(bytes20 username);

    function Registry() {
        addUserValueName("TOKEN_AGE_START");
        addUserValueName("DAY_TRANSFERS_START");
        addUserValueName("DAY_TOTAL");
    }

    function add(bytes20 _username, address _owner) public onlyController {
        usernameToUser[_username] = User({owner: _owner});
        ownerToUsername[_owner] = _username;
        Added(_username);
    }

    function remove(bytes20 _username) public onlyController {
        delete ownerToUsername[usernameToUser[_username].owner];
        delete usernameToUser[_username];
        Removed(_username);
    }

    function addUserValueName(bytes20 _valueName) public onlyController {
        userValueNames.push(_valueName);
    }

    function getOwner(bytes20 _username) public returns(address owner) {
        owner = usernameToUser[_username].owner;
    }

    function getUserValue(bytes20 _username, uint _valueIdx) public returns(uint value) {
        value = usernameToUser[_username].values[_valueIdx];
    }

    function setUserValue(bytes20 _username, uint _valueIdx, uint _value) public onlyController {
        usernameToUser[_username].values[_valueIdx] = _value;
    }

}