burnAssessor function

burnAssessor function

pragma solidity ^0.4.11;

import "./Math.sol";
import "./Concept.sol";
import "./FathomToken.sol";

contract Assessment {
    address assessee;
    address[] assessors;

    mapping (address => State) assessorState;
    State public assessmentStage;
    enum State {
        None,
        Called,
        Confirmed,
        Committed,
        Done,
        Burned
    }

    address concept;
    address fathomToken;

    uint public endTime;
    // will keep track of timelimits for 1) latest possible time to confirm and
    // 2) earliest time to reveal
    uint public checkpoint;
    uint public size;
    uint cost;

    mapping(address => bytes32) commits;
    uint public done; //counter how many assessors have committed/revealed their score
    mapping(address => int128) scores;
    int public finalScore;

    modifier onlyConcept() {
        require(msg.sender == concept);
        _;
    }

    modifier onlyInStage(State _stage) {
        require(assessmentStage == _stage);
        _;
    }

    function Assessment(address _assessee,
                        uint _size,
                        uint _cost,
                        uint _confirmTime,
                        uint _timeLimit) {
        assessee = _assessee;
        concept = msg.sender;
        fathomToken = Concept(concept).fathomToken();

        endTime = now + _timeLimit;
        // set checkpoint to latest possible time to confirm
        checkpoint = now + _confirmTime;
        assert(checkpoint < endTime);

        size = _size;
        cost = _cost;

        FathomToken(fathomToken).notification(assessee, 0); // assesse has started an assessment
        done = 0;
    }

    function cancelAssessment() private {
        FathomToken(fathomToken).transfer(assessee, cost*size);
        FathomToken(fathomToken).notification(assessee, 3); //Assessment Cancled and you have been refunded
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] != State.Burned) {
                FathomToken(fathomToken).transfer(assessors[i], cost);
                FathomToken(fathomToken).notification(assessors[i], 3); //Assessment Cancled and you have been refunded
            }
        }
        suicide(concept);
    }

    //@purpose: adds a user to the pool eligible to accept an assessment
    function addAssessorToPool(address assessor) onlyConcept() returns(bool) {
        if (assessor != assessee && assessorState[assessor] == State.None) {
            FathomToken(fathomToken).notification(assessor, 1); //Called As A Potential Assessor
            assessorState[assessor] = State.Called;
            return true;
        }
        else {
            return false;
        }
    }

    /*
      @purpose: To recursively set the pool to draw assessors from in the assessment
      stops when the pool of potential assessors is 20 times the size of the assessment2
      @param: uint seed = the seed number for random number generation
      @param: address _concept = the concept being called from
      @param: uint num = the total number of assessors to be called
    */
    function setAssessorPool(uint seed, address _concept, uint num) onlyConcept() {
        uint numCalled = 0;
        uint membersOfConcept = Concept(_concept).getMemberLength();
        //we want to call at most half of the members of each concept
        uint maxFromThisPool = num > membersOfConcept/2 ? membersOfConcept/2 : num;
        for (uint k=0; k < maxFromThisPool; k++) {
            address randomUser = Concept(_concept).getWeightedRandomMember(seed + k);
            if (randomUser != address(0x0) && addAssessorToPool(randomUser)) {
                numCalled++;
            }
        }
        uint remaining = num - numCalled;
        if (remaining > 0) {
            for (uint i = 0; i < Concept(_concept).getParentsLength(); i++) {
                setAssessorPool(seed + numCalled + i, Concept(_concept).parents(i), remaining/Concept(_concept).getParentsLength() + 1); //Calls the remaining users from the parent concepts proportional to their size
            }
        }
        assessmentStage = State.Called;
    }

    //@purpose: called by an assessor to confirm and stake
    function confirmAssessor() onlyInStage(State.Called) {
        // cancel if the assessment is older than 12 hours or already past its timelimit
        if (now > checkpoint){
            cancelAssessment();
            return;
        }
        if (assessorState[msg.sender] == State.Called &&
            assessors.length < size &&
            FathomToken(fathomToken).takeBalance(msg.sender, address(this), cost, concept)
            ) {
            assessors.push(msg.sender);
            assessorState[msg.sender] = State.Confirmed;
            FathomToken(fathomToken).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
        }
        if (assessors.length == size) {
            notifyAssessors(uint(State.Confirmed), 4);
            FathomToken(fathomToken).notification(assessee, 4);
            assessmentStage = State.Confirmed;
        }
    }

    //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
    function commit(bytes32 _hash) onlyInStage(State.Confirmed) {
        if (now > endTime) {
            burnStakes();
        }
        if (assessorState[msg.sender] == State.Confirmed) {
                commits[msg.sender] = _hash;
                assessorState[msg.sender] = State.Committed;
                done++; //Increases done by 1 to help progress to the next assessment stage.
        }
        if (done == size) {
            //set checkpoint to end of 12 hour challenge period after which scores can be revealed
            checkpoint = now + 12 hours;
            notifyAssessors(uint(State.Committed), 5);
            done = 0; //Resets the done counter
            assessmentStage = State.Committed;
        }
    }

    function steal(int128 _score, string _salt, address assessor) {
        if(assessorState[assessor] == State.Committed) {
            if(commits[assessor] == sha3(_score, _salt)) {
                FathomToken(fathomToken).transfer(msg.sender, cost/2);
                assessorState[assessor] = State.Burned;
                size--;
            }
        }
    }

    //@purpose: called by assessors to reveal their own commits or others
    // must be called between 12 hours after the latest commit and 24 hours after the
    // end of the assessment. If the last commit happens during at the last possible
    // point in time (right before endtime), this period will be 12hours
    function reveal(int128 _score, string _salt) onlyInStage(State.Committed) {
        // scores can only be revealed after the challenge period has passed
        require(now > checkpoint);
        // If the time to reveal has passed, burn all unrevealed assessors
        if (now > endTime + 24 hours) {
            for (uint i = 0; i < assessors.length; i++) {
                if (assessorState[assessors[i]] == State.Committed) {
                    burnAssessor(address(0x0), i);
                }
            }
        }

        if(assessorState[msg.sender] == State.Committed &&
           commits[msg.sender] == sha3(_score, _salt)) {
                    scores[msg.sender] = _score;
                    assessorState[msg.sender] = State.Done;
                    done++;
        }

        if (done == size) {
            assessmentStage = State.Done;
            calculateResult();
        }
    }

    //@purpose: burns stakes of all assessors who are committed
    function burnStakes() private {
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Confirmed) {
                burnAssessor(address(0x0), i);
           }
        }
    }

    /* @purpose: mark an assessor as burned, reduce size and cancel assessment
      if the size is below five.
      @param _assessor address of the assessor to be burned
      @param _idx index of the assessor in the assessor array (only used if the assessor address is zero)
    */
    function burnAssessor(address _assessor, uint _idx) private {
        assessorState[_assessor != address(0x0) ? _assessor : assessors[_idx]] = State.Burned;
        if (--size < 5) {
            cancelAssessment();
        }
    }

    function notifyAssessors(uint _state, uint _topic) private {
        for (uint i=0; i < assessors.length; i++) {
            if (uint(assessorState[assessors[i]]) == _state) {
                FathomToken(fathomToken).notification(assessors[i], _topic);
            }
        }
    }

    function calculateResult() onlyInStage(State.Done) private {
        int[] memory finalScores = new int[] (done);
        uint idx =0;
        for (uint j = 0; j < assessors.length; j++) {
            if (assessorState[assessors[j]] == State.Done) {
                finalScores[idx] = scores[assessors[j]];
                idx++;
            }
        }
        uint mad = Math.calculateMAD(finalScores);
        uint finalClusterLength;
        (finalScore, finalClusterLength) = Math.getFinalScore(finalScores, mad);
        payout(mad);
        if (finalScore > 0) {
            Concept(concept).addMember(assessee, uint(finalScore) * finalClusterLength);
        }
        FathomToken(fathomToken).notification(assessee, 7);
   }

    function payout(uint mad) onlyInStage(State.Done) private {
        uint q = 1; //INFLATION RATE
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Done) {
                uint payoutValue = Math.getPayout(Math.abs(scores[assessors[i]] - finalScore), mad, cost, q);
                FathomToken(fathomToken).transfer(assessors[i], payoutValue);
                FathomToken(fathomToken).notification(assessors[i], 6); //You  got paid!
            }
        }
    }
}

pragma solidity ^0.4.11;

import "./Math.sol";
import "./Concept.sol";
import "./FathomToken.sol";

contract Assessment {
    address assessee;
    address[] assessors;

    mapping (address => State) assessorState;
    State public assessmentStage;
    enum State {
        None,
        Called,
        Confirmed,
        Committed,
        Done,
        Burned
    }

    address concept;
    address fathomToken;

    uint public endTime;
    // will keep track of timelimits for 1) latest possible time to confirm and
    // 2) earliest time to reveal
    uint public checkpoint;
    uint public size;
    uint cost;

    mapping(address => bytes32) commits;
    uint public done; //counter how many assessors have committed/revealed their score
    mapping(address => int128) scores;
    int public finalScore;

    modifier onlyConcept() {
        require(msg.sender == concept);
        _;
    }

    modifier onlyInStage(State _stage) {
        require(assessmentStage == _stage);
        _;
    }

    function Assessment(address _assessee,
                        uint _size,
                        uint _cost,
                        uint _confirmTime,
                        uint _timeLimit) {
        assessee = _assessee;
        concept = msg.sender;
        fathomToken = Concept(concept).fathomToken();

        endTime = now + _timeLimit;
        // set checkpoint to latest possible time to confirm
        checkpoint = now + _confirmTime;
        assert(checkpoint < endTime);

        size = _size;
        cost = _cost;

        FathomToken(fathomToken).notification(assessee, 0); // assesse has started an assessment
        done = 0;
    }

    function cancelAssessment() internal {
        FathomToken(fathomToken).transfer(assessee, cost*size);
        FathomToken(fathomToken).notification(assessee, 3); //Assessment Cancled and you have been refunded
        for (uint i = 0; i < assessors.length; i++) {
            FathomToken(fathomToken).transfer(assessors[i], cost);
            FathomToken(fathomToken).notification(assessors[i], 3); //Assessment Cancled and you have been refunded
        }
        suicide(concept);
    }

    //@purpose: adds a user to the pool eligible to accept an assessment
    function addAssessorToPool(address assessor) onlyConcept() returns(bool) {
        if (assessor != assessee && assessorState[assessor] == State.None) {
            FathomToken(fathomToken).notification(assessor, 1); //Called As A Potential Assessor
            assessorState[assessor] = State.Called;
            return true;
        }
        else {
            return false;
        }
    }

    /*
      @purpose: To recursively set the pool to draw assessors from in the assessment
      stops when the pool of potential assessors is 20 times the size of the assessment2
      @param: uint seed = the seed number for random number generation
      @param: address _concept = the concept being called from
      @param: uint num = the total number of assessors to be called
    */
    function setAssessorPool(uint seed, address _concept, uint num) onlyConcept() {
        uint numCalled = 0;
        uint membersOfConcept = Concept(_concept).getMemberLength();
        //we want to call at most half of the members of each concept
        uint maxFromThisPool = num > membersOfConcept/2 ? membersOfConcept/2 : num;
        for (uint k=0; k < maxFromThisPool; k++) {
            address randomUser = Concept(_concept).getWeightedRandomMember(seed + k);
            if (randomUser != address(0x0) && addAssessorToPool(randomUser)) {
                numCalled++;
            }
        }
        uint remaining = num - numCalled;
        if (remaining > 0) {
            for (uint i = 0; i < Concept(_concept).getParentsLength(); i++) {
                setAssessorPool(seed + numCalled + i, Concept(_concept).parents(i), remaining/Concept(_concept).getParentsLength() + 1); //Calls the remaining users from the parent concepts proportional to their size
            }
        }
        assessmentStage = State.Called;
    }

    //@purpose: called by an assessor to confirm and stake
    function confirmAssessor() onlyInStage(State.Called) {
        // cancel if the assessment is older than 12 hours or already past its timelimit
        if (now > checkpoint){
            cancelAssessment();
            return;
        }
        if (assessorState[msg.sender] == State.Called &&
            assessors.length < size &&
            FathomToken(fathomToken).takeBalance(msg.sender, address(this), cost, concept)
            ) {
            assessors.push(msg.sender);
            assessorState[msg.sender] = State.Confirmed;
            FathomToken(fathomToken).notification(msg.sender, 2); //Confirmed for assessing, stake has been taken
        }
        if (assessors.length == size) {
            notifyAssessors(uint(State.Confirmed), 4);
            FathomToken(fathomToken).notification(assessee, 4);
            assessmentStage = State.Confirmed;
        }
    }

    //@purpose: called by an assessor to commit a hash of their score //TODO explain in more detail what's happening
    function commit(bytes32 _hash) onlyInStage(State.Confirmed) {
        if (now > endTime) {
            burnStakes();
        }
        if (assessorState[msg.sender] == State.Confirmed) {
                commits[msg.sender] = _hash;
                assessorState[msg.sender] = State.Committed;
                done++; //Increases done by 1 to help progress to the next assessment stage.
        }
        if (done == size) {
            //set checkpoint to end of 12 hour challenge period after which scores can be revealed
            checkpoint = now + 12 hours;
            notifyAssessors(uint(State.Committed), 5);
            done = 0; //Resets the done counter
            assessmentStage = State.Committed;
        }
    }

    function steal(int128 _score, string _salt, address assessor) {
        if(assessorState[assessor] == State.Committed) {
            if(commits[assessor] == sha3(_score, _salt)) {
                FathomToken(fathomToken).transfer(msg.sender, cost/2);
                assessorState[assessor] = State.Burned;
                size--;
            }
        }
    }

    //@purpose: called by assessors to reveal their own commits or others
    // must be called between 12 hours after the latest commit and 24 hours after the
    // end of the assessment. If the last commit happens during at the last possible
    // point in time (right before endtime), this period will be 12hours
    function reveal(int128 _score, string _salt) onlyInStage(State.Committed) {
        // scores can only be revealed after the challenge period has passed
        require(now > checkpoint);
        // If the time to reveal has passed, burn all unrevealed assessors
        if (now > endTime + 24 hours) {
            for (uint i = 0; i < assessors.length; i++) {
                if (assessorState[assessors[i]] == State.Committed) {
                    assessorState[assessors[i]] = State.Burned;
                    size--;
                }
            }
        }

        if(assessorState[msg.sender] == State.Committed &&
           commits[msg.sender] == sha3(_score, _salt)) {
                    scores[msg.sender] = _score;
                    assessorState[msg.sender] = State.Done;
                    done++;
        }

        if (done == size) {
            assessmentStage = State.Done;
            calculateResult();
        }
    }

    //@purpose: burns stakes as a function of how much time has passed since half of the assessors commited
    function burnStakes() internal {
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Confirmed) {
                assessorState[assessors[i]] = State.Burned;
                size--; //decrease size to help progress to the next assessment stage
           }
        }
    }

    function notifyAssessors(uint _state, uint _topic) private {
        for (uint i=0; i < assessors.length; i++) {
            if (uint(assessorState[assessors[i]]) == _state) {
                FathomToken(fathomToken).notification(assessors[i], _topic);
            }
        }
    }

    function calculateResult() onlyInStage(State.Done) private {
        int[] memory finalScores = new int[] (done);
        uint idx =0;
        for (uint j = 0; j < assessors.length; j++) {
            if (assessorState[assessors[j]] == State.Done) {
                finalScores[idx] = scores[assessors[j]];
                idx++;
            }
        }
        uint mad = Math.calculateMAD(finalScores);
        uint finalClusterLength;
        (finalScore, finalClusterLength) = Math.getFinalScore(finalScores, mad);
        payout(mad);
        if (finalScore > 0) {
            Concept(concept).addMember(assessee, uint(finalScore) * finalClusterLength);
        }
        FathomToken(fathomToken).notification(assessee, 7);
   }

    function payout(uint mad) onlyInStage(State.Done) internal {
        uint q = 1; //INFLATION RATE
        for (uint i = 0; i < assessors.length; i++) {
            if (assessorState[assessors[i]] == State.Done) {
                uint payoutValue = Math.getPayout(Math.abs(scores[assessors[i]] - finalScore), mad, cost, q);
                FathomToken(fathomToken).transfer(assessors[i], payoutValue);
                FathomToken(fathomToken).notification(assessors[i], 6); //You  got paid!
            }
        }
    }
}


Add the missing nonce check

Add the missing nonce check

import "Rules.sol";

contract Adjudicator {

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes32[] state;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	modifier nonceUpdate(uint _newNonce) {
		if (_newNonce > nonce) {
			nonce = _newNonce;
			_
		} else {
			throw;
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function getStateLength() constant returns (uint) {
		return state.length;
	}

	function getStateAt(uint _index) constant returns (bytes32) {
		return state[_index];
	}

	function submit(uint _newNonce, bytes32[] _state)
		external
		onlyOwner
		notFrozen
		nonceUpdate(_newNonce)
	{
		state = _state;
	}

	function appeal(uint _newNonce, Rules _rules, bytes4 _methodSignature, bytes32[] _arguments)
		external
		onlyOwner
		notFrozen
		nonceUpdate(_newNonce)
	{
		if (!_rules.call(_methodSignature, _arguments)) {
			throw;
		}

		state.length = _rules.getDecidedStateLength();
		for (uint i = 0; i < state.length; i++) {
			state[i] = _rules.getDecidedStateAt(i);
		}
	}

	function giveConsent() external onlyOwner notFrozen {
		frozen = true;
	}

	function finalize() external notFrozen returns (bool) {
		if (lastTimestamp > 0 && now > lastTimestamp + timeout) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}

import "Rules.sol";

contract Adjudicator {

	bool public frozen = false;
	uint nonce = 0;
	uint lastTimestamp = 0;
	address owner;
	uint timeout;
	bytes32[] state;

	modifier onlyOwner {
		if (msg.sender == owner) {
			_
		} else {
			throw;
		}
	}

	modifier notFrozen {
		if (frozen) {
			throw;
		} else {
			_
		}
	}

	function Adjudicator(address _owner, uint _timeout) {
		owner = _owner;
		timeout = _timeout;
	}

	function getStateLength() constant returns (uint) {
		return state.length;
	}

	function getStateAt(uint _index) constant returns (bytes32) {
		return state[_index];
	}

	function submit(bytes32[] _state) external onlyOwner notFrozen {
		state = _state;
	}

	function appeal(Rules _rules, bytes4 _methodSignature, bytes32[] _arguments) external onlyOwner notFrozen {
		if (!_rules.call(_methodSignature, _arguments)) {
			throw;
		}

		state.length = _rules.getDecidedStateLength();
		for (uint i = 0; i < state.length; i++) {
			state[i] = _rules.getDecidedStateAt(i);
		}
	}

	function giveConsent() external onlyOwner notFrozen {
		frozen = true;
	}

	function finalize() external notFrozen returns (bool) {
		if (lastTimestamp > 0 && now > lastTimestamp + timeout) {
			frozen = true;
			return true;
		} else {
			return false;
		}
	}

	function kill(address _recipient) external onlyOwner {
		selfdestruct(_recipient);
	}
}


remove nodeid

remove nodeid

// Grove v0.2

/// @title GroveLib - Library for queriable indexed ordered data.
/// @author PiperMerriam - <pipermerriam@gmail.com>
library GroveLib {
        /*
         *  Indexes for ordered data
         *
         *  Address: 0xd07ce4329b27eb8896c51458468d98a0e4c0394c
         */
        struct Index {
                bytes32 root;
                mapping (bytes32 => Node) nodes;
        }

        struct Node {
                bytes32 id;
                int value;
                bytes32 parent;
                bytes32 left;
                bytes32 right;
                uint height;
        }

        function max(uint a, uint b) internal returns (uint) {
            if (a >= b) {
                return a;
            }
            return b;
        }

        /*
         *  Node getters
         */
        /// @dev Retrieve the value for the node.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getNodeValue(Index storage index, bytes32 id) constant returns (int) {
            return index.nodes[id].value;
        }

        /// @dev Retrieve the height of the node.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getNodeHeight(Index storage index, bytes32 id) constant returns (uint) {
            return index.nodes[id].height;
        }

        /// @dev Retrieve the parent id of the node.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getNodeParent(Index storage index, bytes32 id) constant returns (bytes32) {
            return index.nodes[id].parent;
        }

        /// @dev Retrieve the left child id of the node.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getNodeLeftChild(Index storage index, bytes32 id) constant returns (bytes32) {
            return index.nodes[id].left;
        }

        /// @dev Retrieve the right child id of the node.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getNodeRightChild(Index storage index, bytes32 id) constant returns (bytes32) {
            return index.nodes[id].right;
        }

        /// @dev Retrieve the node id of the next node in the tree.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getPreviousNode(Index storage index, bytes32 id) constant returns (bytes32) {
            Node storage currentNode = index.nodes[id];

            if (currentNode.id == 0x0) {
                // Unknown node, just return 0x0;
                return 0x0;
            }

            Node memory child;

            if (currentNode.left != 0x0) {
                // Trace left to latest child in left tree.
                child = index.nodes[currentNode.left];

                while (child.right != 0) {
                    child = index.nodes[child.right];
                }
                return child.id;
            }

            if (currentNode.parent != 0x0) {
                // Now we trace back up through parent relationships, looking
                // for a link where the child is the right child of it's
                // parent.
                Node storage parent = index.nodes[currentNode.parent];
                child = currentNode;

                while (true) {
                    if (parent.right == child.id) {
                        return parent.id;
                    }

                    if (parent.parent == 0x0) {
                        break;
                    }
                    child = parent;
                    parent = index.nodes[parent.parent];
                }
            }

            // This is the first node, and has no previous node.
            return 0x0;
        }

        /// @dev Retrieve the node id of the previous node in the tree.
        /// @param index The index that the node is part of.
        /// @param id The id for the node to be looked up.
        function getNextNode(Index storage index, bytes32 id) constant returns (bytes32) {
            Node storage currentNode = index.nodes[id];

            if (currentNode.id == 0x0) {
                // Unknown node, just return 0x0;
                return 0x0;
            }

            Node memory child;

            if (currentNode.right != 0x0) {
                // Trace right to earliest child in right tree.
                child = index.nodes[currentNode.right];

                while (child.left != 0) {
                    child = index.nodes[child.left];
                }
                return child.id;
            }

            if (currentNode.parent != 0x0) {
                // if the node is the left child of it's parent, then the
                // parent is the next one.
                Node storage parent = index.nodes[currentNode.parent];
                child = currentNode;

                while (true) {
                    if (parent.left == child.id) {
                        return parent.id;
                    }

                    if (parent.parent == 0x0) {
                        break;
                    }
                    child = parent;
                    parent = index.nodes[parent.parent];
                }

                // Now we need to trace all the way up checking to see if any parent is the
            }

            // This is the final node.
            return 0x0;
        }

        /// @dev Updates or Inserts the id into the index at its appropriate location based on the value provided.
        /// @param index The index that the node is part of.
        /// @param id The unique identifier of the data element the index node will represent.
        /// @param value The value of the data element that represents it's total ordering with respect to other elementes.
        function insert(Index storage index, bytes32 id, int value) public {
                if (index.nodes[id].id == id) {
                    // A node with this id already exists.  If the value is
                    // the same, then just return early, otherwise, remove it
                    // and reinsert it.
                    if (index.nodes[id].value == value) {
                        return;
                    }
                    remove(index, id);
                }

                uint leftHeight;
                uint rightHeight;

                bytes32 previousNodeId = 0x0;

                bytes32 rootNodeId = index.root;

                if (rootNodeId == 0x0) {
                    rootNodeId = id;
                    index.root = id;
                }
                Node storage currentNode = index.nodes[rootNodeId];

                // Do insertion
                while (true) {
                    if (currentNode.id == 0x0) {
                        // This is a new unpopulated node.
                        currentNode.id = id;
                        currentNode.parent = previousNodeId;
                        currentNode.value = value;
                        break;
                    }

                    // Set the previous node id.
                    previousNodeId = currentNode.id;

                    // The new node belongs in the right subtree
                    if (value >= currentNode.value) {
                        if (currentNode.right == 0x0) {
                            currentNode.right = id;
                        }
                        currentNode = index.nodes[currentNode.right];
                        continue;
                    }

                    // The new node belongs in the left subtree.
                    if (currentNode.left == 0x0) {
                        currentNode.left = id;
                    }
                    currentNode = index.nodes[currentNode.left];
                }

                // Rebalance the tree
                _rebalanceTree(index, currentNode.id);
        }

        /// @dev Checks whether a node for the given unique identifier exists within the given index.
        /// @param index The index that should be searched
        /// @param id The unique identifier of the data element to check for.
        function exists(Index storage index, bytes32 id) constant returns (bool) {
            return (index.nodes[id].id == id);
        }

        /// @dev Remove the node for the given unique identifier from the index.
        /// @param index The index that should be removed
        /// @param id The unique identifier of the data element to remove.
        function remove(Index storage index, bytes32 id) public {
            Node storage replacementNode;
            Node storage parent;
            Node storage child;
            bytes32 rebalanceOrigin;

            Node storage nodeToDelete = index.nodes[id];

            if (nodeToDelete.id != id) {
                // The id does not exist in the tree.
                return;
            }

            if (nodeToDelete.left != 0x0 || nodeToDelete.right != 0x0) {
                // This node is not a leaf node and thus must replace itself in
                // it's tree by either the previous or next node.
                if (nodeToDelete.left != 0x0) {
                    // This node is guaranteed to not have a right child.
                    replacementNode = index.nodes[getPreviousNode(index, nodeToDelete.id)];
                }
                else {
                    // This node is guaranteed to not have a left child.
                    replacementNode = index.nodes[getNextNode(index, nodeToDelete.id)];
                }
                // The replacementNode is guaranteed to have a parent.
                parent = index.nodes[replacementNode.parent];

                // Keep note of the location that our tree rebalancing should
                // start at.
                rebalanceOrigin = replacementNode.id;

                // Join the parent of the replacement node with any subtree of
                // the replacement node.  We can guarantee that the replacement
                // node has at most one subtree because of how getNextNode and
                // getPreviousNode are used.
                if (parent.left == replacementNode.id) {
                    parent.left = replacementNode.right;
                    if (replacementNode.right != 0x0) {
                        child = index.nodes[replacementNode.right];
                        child.parent = parent.id;
                    }
                }
                if (parent.right == replacementNode.id) {
                    parent.right = replacementNode.left;
                    if (replacementNode.left != 0x0) {
                        child = index.nodes[replacementNode.left];
                        child.parent = parent.id;
                    }
                }

                // Now we replace the nodeToDelete with the replacementNode.
                // This includes parent/child relationships for all of the
                // parent, the left child, and the right child.
                replacementNode.parent = nodeToDelete.parent;
                if (nodeToDelete.parent != 0x0) {
                    parent = index.nodes[nodeToDelete.parent];
                    if (parent.left == nodeToDelete.id) {
                        parent.left = replacementNode.id;
                    }
                    if (parent.right == nodeToDelete.id) {
                        parent.right = replacementNode.id;
                    }
                }
                else {
                    // If the node we are deleting is the root node so update
                    // the index root
                    index.root = replacementNode.id;
                }

                replacementNode.left = nodeToDelete.left;
                if (nodeToDelete.left != 0x0) {
                    child = index.nodes[nodeToDelete.left];
                    child.parent = replacementNode.id;
                }

                replacementNode.right = nodeToDelete.right;
                if (nodeToDelete.right != 0x0) {
                    child = index.nodes[nodeToDelete.right];
                    child.parent = replacementNode.id;
                }
            }
            else if (nodeToDelete.parent != 0x0) {
                // The node being deleted is a leaf node so we only erase it's
                // parent linkage.
                parent = index.nodes[nodeToDelete.parent];

                if (parent.left == nodeToDelete.id) {
                    parent.left = 0x0;
                }
                if (parent.right == nodeToDelete.id) {
                    parent.right = 0x0;
                }

                // keep note of where the rebalancing should begin.
                rebalanceOrigin = parent.id;
            }
            else {
                // This is both a leaf node and the root node, so we need to
                // unset the root node pointer.
                index.root = 0x0;
            }

            // Now we zero out all of the fields on the nodeToDelete.
            nodeToDelete.id = 0x0;
            nodeToDelete.value = 0;
            nodeToDelete.parent = 0x0;
            nodeToDelete.left = 0x0;
            nodeToDelete.right = 0x0;

            // Walk back up the tree rebalancing
            if (rebalanceOrigin != 0x0) {
                _rebalanceTree(index, rebalanceOrigin);
            }
        }

        bytes2 constant GT = ">";
        bytes2 constant LT = "<";
        bytes2 constant GTE = ">=";
        bytes2 constant LTE = "<=";
        bytes2 constant EQ = "==";

        function _compare(int left, bytes2 operator, int right) internal returns (bool) {
            if (operator == GT) {
                return (left > right);
            }
            if (operator == LT) {
                return (left < right);
            }
            if (operator == GTE) {
                return (left >= right);
            }
            if (operator == LTE) {
                return (left <= right);
            }
            if (operator == EQ) {
                return (left == right);
            }

            // Invalid operator.
            throw;
        }

        function _getMaximum(Index storage index, bytes32 id) internal returns (int) {
                Node storage currentNode = index.nodes[id];

                while (true) {
                    if (currentNode.right == 0x0) {
                        return currentNode.value;
                    }
                    currentNode = index.nodes[currentNode.right];
                }
        }

        function _getMinimum(Index storage index, bytes32 id) internal returns (int) {
                Node storage currentNode = index.nodes[id];

                while (true) {
                    if (currentNode.left == 0x0) {
                        return currentNode.value;
                    }
                    currentNode = index.nodes[currentNode.left];
                }
        }

        /** @dev Query the index for the edge-most node that satisfies the
         *  given query.  For >, >=, and ==, this will be the left-most node
         *  that satisfies the comparison.  For < and <= this will be the
         *  right-most node that satisfies the comparison.
         */
        /// @param index The index that should be queried
        /** @param operator One of '>', '>=', '<', '<=', '==' to specify what
         *  type of comparison operator should be used.
         */
        function query(Index storage index, bytes2 operator, int value) public returns (bytes32) {
                bytes32 rootNodeId = index.root;

                if (rootNodeId == 0x0) {
                    // Empty tree.
                    return 0x0;
                }

                Node storage currentNode = index.nodes[rootNodeId];

                while (true) {
                    if (_compare(currentNode.value, operator, value)) {
                        // We have found a match but it might not be the
                        // *correct* match.
                        if ((operator == LT) || (operator == LTE)) {
                            // Need to keep traversing right until this is no
                            // longer true.
                            if (currentNode.right == 0x0) {
                                return currentNode.id;
                            }
                            if (_compare(_getMinimum(index, currentNode.right), operator, value)) {
                                // There are still nodes to the right that
                                // match.
                                currentNode = index.nodes[currentNode.right];
                                continue;
                            }
                            return currentNode.id;
                        }

                        if ((operator == GT) || (operator == GTE) || (operator == EQ)) {
                            // Need to keep traversing left until this is no
                            // longer true.
                            if (currentNode.left == 0x0) {
                                return currentNode.id;
                            }
                            if (_compare(_getMaximum(index, currentNode.left), operator, value)) {
                                currentNode = index.nodes[currentNode.left];
                                continue;
                            }
                            return currentNode.id;
                        }
                    }

                    if ((operator == LT) || (operator == LTE)) {
                        if (currentNode.left == 0x0) {
                            // There are no nodes that are less than the value
                            // so return null.
                            return 0x0;
                        }
                        currentNode = index.nodes[currentNode.left];
                        continue;
                    }

                    if ((operator == GT) || (operator == GTE)) {
                        if (currentNode.right == 0x0) {
                            // There are no nodes that are greater than the value
                            // so return null.
                            return 0x0;
                        }
                        currentNode = index.nodes[currentNode.right];
                        continue;
                    }

                    if (operator == EQ) {
                        if (currentNode.value < value) {
                            if (currentNode.right == 0x0) {
                                return 0x0;
                            }
                            currentNode = index.nodes[currentNode.right];
                            continue;
                        }

                        if (currentNode.value > value) {
                            if (currentNode.left == 0x0) {
                                return 0x0;
                            }
                            currentNode = index.nodes[currentNode.left];
                            continue;
                        }
                    }
                }
        }

        function _rebalanceTree(Index storage index, bytes32 id) internal {
            // Trace back up rebalancing the tree and updating heights as
            // needed..
            Node storage currentNode = index.nodes[id];

            while (true) {
                int balanceFactor = _getBalanceFactor(index, currentNode.id);

                if (balanceFactor == 2) {
                    // Right rotation (tree is heavy on the left)
                    if (_getBalanceFactor(index, currentNode.left) == -1) {
                        // The subtree is leaning right so it need to be
                        // rotated left before the current node is rotated
                        // right.
                        _rotateLeft(index, currentNode.left);
                    }
                    _rotateRight(index, currentNode.id);
                }

                if (balanceFactor == -2) {
                    // Left rotation (tree is heavy on the right)
                    if (_getBalanceFactor(index, currentNode.right) == 1) {
                        // The subtree is leaning left so it need to be
                        // rotated right before the current node is rotated
                        // left.
                        _rotateRight(index, currentNode.right);
                    }
                    _rotateLeft(index, currentNode.id);
                }

                if ((-1 <= balanceFactor) && (balanceFactor <= 1)) {
                    _updateNodeHeight(index, currentNode.id);
                }

                if (currentNode.parent == 0x0) {
                    // Reached the root which may be new due to tree
                    // rotation, so set it as the root and then break.
                    break;
                }

                currentNode = index.nodes[currentNode.parent];
            }
        }

        function _getBalanceFactor(Index storage index, bytes32 id) internal returns (int) {
                Node storage node = index.nodes[id];

                return int(index.nodes[node.left].height) - int(index.nodes[node.right].height);
        }

        function _updateNodeHeight(Index storage index, bytes32 id) internal {
                Node storage node = index.nodes[id];

                node.height = max(index.nodes[node.left].height, index.nodes[node.right].height) + 1;
        }

        function _rotateLeft(Index storage index, bytes32 id) internal {
            Node storage originalRoot = index.nodes[id];

            if (originalRoot.right == 0x0) {
                // Cannot rotate left if there is no right originalRoot to rotate into
                // place.
                throw;
            }

            // The right child is the new root, so it gets the original
            // `originalRoot.parent` as it's parent.
            Node storage newRoot = index.nodes[originalRoot.right];
            newRoot.parent = originalRoot.parent;

            // The original root needs to have it's right child nulled out.
            originalRoot.right = 0x0;

            if (originalRoot.parent != 0x0) {
                // If there is a parent node, it needs to now point downward at
                // the newRoot which is rotating into the place where `node` was.
                Node storage parent = index.nodes[originalRoot.parent];

                // figure out if we're a left or right child and have the
                // parent point to the new node.
                if (parent.left == originalRoot.id) {
                    parent.left = newRoot.id;
                }
                if (parent.right == originalRoot.id) {
                    parent.right = newRoot.id;
                }
            }

            if (newRoot.left != 0) {
                // If the new root had a left child, that moves to be the
                // new right child of the original root node
                Node storage leftChild = index.nodes[newRoot.left];
                originalRoot.right = leftChild.id;
                leftChild.parent = originalRoot.id;
            }

            // Update the newRoot's left node to point at the original node.
            originalRoot.parent = newRoot.id;
            newRoot.left = originalRoot.id;

            if (newRoot.parent == 0x0) {
                index.root = newRoot.id;
            }

            // TODO: are both of these updates necessary?
            _updateNodeHeight(index, originalRoot.id);
            _updateNodeHeight(index, newRoot.id);
        }

        function _rotateRight(Index storage index, bytes32 id) internal {
            Node storage originalRoot = index.nodes[id];

            if (originalRoot.left == 0x0) {
                // Cannot rotate right if there is no left node to rotate into
                // place.
                throw;
            }

            // The left child is taking the place of node, so we update it's
            // parent to be the original parent of the node.
            Node storage newRoot = index.nodes[originalRoot.left];
            newRoot.parent = originalRoot.parent;

            // Null out the originalRoot.left
            originalRoot.left = 0x0;

            if (originalRoot.parent != 0x0) {
                // If the node has a parent, update the correct child to point
                // at the newRoot now.
                Node storage parent = index.nodes[originalRoot.parent];

                if (parent.left == originalRoot.id) {
                    parent.left = newRoot.id;
                }
                if (parent.right == originalRoot.id) {
                    parent.right = newRoot.id;
                }
            }

            if (newRoot.right != 0x0) {
                Node storage rightChild = index.nodes[newRoot.right];
                originalRoot.left = newRoot.right;
                rightChild.parent = originalRoot.id;
            }

            // Update the new root's right node to point to the original node.
            originalRoot.parent = newRoot.id;
            newRoot.right = originalRoot.id;

            if (newRoot.parent == 0x0) {
                index.root = newRoot.id;
            }

            // Recompute heights.
            _updateNodeHeight(index, originalRoot.id);
            _updateNodeHeight(index, newRoot.id);
        }
}

/// @title Grove - queryable indexes for ordered data.
/// @author Piper Merriam <pipermerriam@gmail.com>
contract Grove {
        /*
         *  Indexes for ordered data
         *
         *  Address: 0x8017f24a47c889b1ee80501ff84beb3c017edf0b
         */
        // Map index_id to index
        mapping (bytes32 => GroveLib.Index) index_lookup;

        // Map node_id to index_id.
        mapping (bytes32 => bytes32) node_to_index;

        /// @notice Computes the id for a Grove index which is sha3(owner, indexName)
        /// @param owner The address of the index owner.
        /// @param indexName The name of the index.
        function computeIndexId(address owner, bytes32 indexName) constant returns (bytes32) {
                return GroveLib.computeIndexId(owner, indexName);
        }

        /// @notice Computes the id for a node in a given Grove index which is sha3(indexId, id)
        /// @param indexId The id for the index the node belongs to.
        /// @param id The unique identifier for the data this node represents.
        function computeNodeId(bytes32 indexId, bytes32 id) constant returns (bytes32) {
                return GroveLib.computeNodeId(indexId, id);
        }

        /*
         *  Node getters
         */
        /// @notice Retrieves the name of an index.
        /// @param indexId The id of the index.
        function getIndexName(bytes32 indexId) constant returns (bytes32) {
            return index_lookup[indexId].name;
        }

        /// @notice Retrieves the id of the root node for this index.
        /// @param indexId The id of the index.
        function getIndexRoot(bytes32 indexId) constant returns (bytes32) {
            return index_lookup[indexId].root;
        }

        /// @dev Retrieve the unique identifier this node represents.
        /// @param nodeId The id for the node
        function getNodeId(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeId(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the index id for the node.
        /// @param nodeId The id for the node
        function getNodeIndexId(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeIndexId(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the value of the node.
        /// @param nodeId The id for the node
        function getNodeValue(bytes32 nodeId) constant returns (int) {
            return GroveLib.getNodeValue(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the height of the node.
        /// @param nodeId The id for the node
        function getNodeHeight(bytes32 nodeId) constant returns (uint) {
            return GroveLib.getNodeHeight(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the parent id of the node.
        /// @param nodeId The id for the node
        function getNodeParent(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeParent(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the left child id of the node.
        /// @param nodeId The id for the node
        function getNodeLeftChild(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeLeftChild(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the right child id of the node.
        /// @param nodeId The id for the node
        function getNodeRightChild(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeRightChild(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /** @dev Retrieve the id of the node that comes immediately before this
         *  one.  Returns 0x0 if there is no previous node.
         */
        /// @param nodeId The id for the node
        function getPreviousNode(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getPreviousNode(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /** @dev Retrieve the id of the node that comes immediately after this
         *  one.  Returns 0x0 if there is no previous node.
         */
        /// @param nodeId The id for the node
        function getNextNode(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNextNode(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /** @dev Update or Insert a data element represented by the unique
         *  identifier `id` into the index.
         */
        /// @param indexName The human readable name for the index that the node should be upserted into.
        /// @param id The unique identifier that the index node represents.
        /// @param value The number which represents this data elements total ordering.
        function insert(bytes32 indexName, bytes32 id, int value) public {
                bytes32 indexId = computeIndexId(msg.sender, indexName);
                var index = index_lookup[indexId];

                if (index.name != indexName) {
                        // If this is a new index, store it's name and id
                        index.name = indexName;
                        index.id = indexId;
                }

                // Store the mapping from nodeId to the indexId
                node_to_index[computeNodeId(indexId, id)] = indexId;

                GroveLib.insert(index, id, value);
        }

        /// @dev Query whether a node exists within the specified index for the unique identifier.
        /// @param indexId The id for the index.
        /// @param id The unique identifier of the data element.
        function exists(bytes32 indexId, bytes32 id) constant returns (bool) {
            return GroveLib.exists(index_lookup[indexId], id);
        }

        /// @dev Remove the index node for the given unique identifier.
        /// @param indexName The name of the index.
        /// @param id The unique identifier of the data element.
        function remove(bytes32 indexName, bytes32 id) public {
            GroveLib.remove(index_lookup[computeIndexId(msg.sender, indexName)], id);
        }

        /** @dev Query the index for the edge-most node that satisfies the
         * given query.  For >, >=, and ==, this will be the left-most node
         * that satisfies the comparison.  For < and <= this will be the
         * right-most node that satisfies the comparison.
         */
        /// @param indexId The id of the index that should be queried
        /** @param operator One of '>', '>=', '<', '<=', '==' to specify what
         *  type of comparison operator should be used.
         */
        function query(bytes32 indexId, bytes2 operator, int value) public returns (bytes32) {
                return GroveLib.query(index_lookup[indexId], operator, value);
        }
}

// Grove v0.2

/// @title GroveLib - Library for queriable indexed ordered data.
/// @author PiperMerriam - <pipermerriam@gmail.com>
library GroveLib {
        /*
         *  Indexes for ordered data
         *
         *  Address: 0xd07ce4329b27eb8896c51458468d98a0e4c0394c
         */
        struct Index {
                bytes32 id;
                bytes32 name;
                bytes32 root;
                mapping (bytes32 => Node) nodes;
        }

        struct Node {
                bytes32 nodeId;
                bytes32 indexId;
                bytes32 id;
                int value;
                bytes32 parent;
                bytes32 left;
                bytes32 right;
                uint height;
        }

        /// @dev This is merely a shortcut for `sha3(owner, indexName)`
        /// @param owner The address of the owner of this index.
        /// @param indexName The human readable name for this index.
        function computeIndexId(address owner, bytes32 indexName) constant returns (bytes32) {
                return sha3(owner, indexName);
        }

        /// @dev This is merely a shortcut for `sha3(indexId, id)`
        /// @param indexId The id for the index the node belongs to.
        /// @param id The unique identifier for the data this node represents.
        function computeNodeId(bytes32 indexId, bytes32 id) constant returns (bytes32) {
                return sha3(indexId, id);
        }

        function max(uint a, uint b) internal returns (uint) {
            if (a >= b) {
                return a;
            }
            return b;
        }

        /*
         *  Node getters
         */
        /// @dev Retrieve the unique identifier for the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeId(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            return index.nodes[nodeId].id;
        }

        /// @dev Retrieve the index id for the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeIndexId(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            return index.nodes[nodeId].indexId;
        }

        /// @dev Retrieve the value for the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeValue(Index storage index, bytes32 nodeId) constant returns (int) {
            return index.nodes[nodeId].value;
        }

        /// @dev Retrieve the height of the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeHeight(Index storage index, bytes32 nodeId) constant returns (uint) {
            return index.nodes[nodeId].height;
        }

        /// @dev Retrieve the parent id of the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeParent(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            return index.nodes[nodeId].parent;
        }

        /// @dev Retrieve the left child id of the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeLeftChild(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            return index.nodes[nodeId].left;
        }

        /// @dev Retrieve the right child id of the node.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNodeRightChild(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            return index.nodes[nodeId].right;
        }

        /// @dev Retrieve the node id of the next node in the tree.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getPreviousNode(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            Node storage currentNode = index.nodes[nodeId];

            if (currentNode.nodeId == 0x0) {
                // Unknown node, just return 0x0;
                return 0x0;
            }

            Node memory child;

            if (currentNode.left != 0x0) {
                // Trace left to latest child in left tree.
                child = index.nodes[currentNode.left];

                while (child.right != 0) {
                    child = index.nodes[child.right];
                }
                return child.nodeId;
            }

            if (currentNode.parent != 0x0) {
                // Now we trace back up through parent relationships, looking
                // for a link where the child is the right child of it's
                // parent.
                Node storage parent = index.nodes[currentNode.parent];
                child = currentNode;

                while (true) {
                    if (parent.right == child.nodeId) {
                        return parent.nodeId;
                    }

                    if (parent.parent == 0x0) {
                        break;
                    }
                    child = parent;
                    parent = index.nodes[parent.parent];
                }
            }

            // This is the first node, and has no previous node.
            return 0x0;
        }

        /// @dev Retrieve the node id of the previous node in the tree.
        /// @param index The index that the node is part of.
        /// @param nodeId The id for the node to be looked up.
        function getNextNode(Index storage index, bytes32 nodeId) constant returns (bytes32) {
            Node storage currentNode = index.nodes[nodeId];

            if (currentNode.nodeId == 0x0) {
                // Unknown node, just return 0x0;
                return 0x0;
            }

            Node memory child;

            if (currentNode.right != 0x0) {
                // Trace right to earliest child in right tree.
                child = index.nodes[currentNode.right];

                while (child.left != 0) {
                    child = index.nodes[child.left];
                }
                return child.nodeId;
            }

            if (currentNode.parent != 0x0) {
                // if the node is the left child of it's parent, then the
                // parent is the next one.
                Node storage parent = index.nodes[currentNode.parent];
                child = currentNode;

                while (true) {
                    if (parent.left == child.nodeId) {
                        return parent.nodeId;
                    }

                    if (parent.parent == 0x0) {
                        break;
                    }
                    child = parent;
                    parent = index.nodes[parent.parent];
                }

                // Now we need to trace all the way up checking to see if any parent is the
            }

            // This is the final node.
            return 0x0;
        }

        /// @dev Updates or Inserts the id into the index at its appropriate location based on the value provided.
        /// @param index The index that the node is part of.
        /// @param id The unique identifier of the data element the index node will represent.
        /// @param value The value of the data element that represents it's total ordering with respect to other elementes.
        function insert(Index storage index, bytes32 id, int value) public {
                bytes32 nodeId = computeNodeId(index.id, id);

                if (index.nodes[nodeId].nodeId == nodeId) {
                    // A node with this id already exists.  If the value is
                    // the same, then just return early, otherwise, remove it
                    // and reinsert it.
                    if (index.nodes[nodeId].value == value) {
                        return;
                    }
                    remove(index, id);
                }

                uint leftHeight;
                uint rightHeight;

                bytes32 previousNodeId = 0x0;

                bytes32 rootNodeId = index.root;

                if (rootNodeId == 0x0) {
                    rootNodeId = nodeId;
                    index.root = nodeId;
                }
                Node storage currentNode = index.nodes[rootNodeId];

                // Do insertion
                while (true) {
                    if (currentNode.indexId == 0x0) {
                        // This is a new unpopulated node.
                        currentNode.nodeId = nodeId;
                        currentNode.parent = previousNodeId;
                        currentNode.indexId = index.id;
                        currentNode.id = id;
                        currentNode.value = value;
                        break;
                    }

                    // Set the previous node id.
                    previousNodeId = currentNode.nodeId;

                    // The new node belongs in the right subtree
                    if (value >= currentNode.value) {
                        if (currentNode.right == 0x0) {
                            currentNode.right = nodeId;
                        }
                        currentNode = index.nodes[currentNode.right];
                        continue;
                    }

                    // The new node belongs in the left subtree.
                    if (currentNode.left == 0x0) {
                        currentNode.left = nodeId;
                    }
                    currentNode = index.nodes[currentNode.left];
                }

                // Rebalance the tree
                _rebalanceTree(index, currentNode.nodeId);
        }

        /// @dev Checks whether a node for the given unique identifier exists within the given index.
        /// @param index The index that should be searched
        /// @param id The unique identifier of the data element to check for.
        function exists(Index storage index, bytes32 id) constant returns (bool) {
            bytes32 nodeId = computeNodeId(index.id, id);
            return (index.nodes[nodeId].nodeId == nodeId);
        }

        /// @dev Remove the node for the given unique identifier from the index.
        /// @param index The index that should be removed
        /// @param id The unique identifier of the data element to remove.
        function remove(Index storage index, bytes32 id) public {
            bytes32 nodeId = computeNodeId(index.id, id);

            Node storage replacementNode;
            Node storage parent;
            Node storage child;
            bytes32 rebalanceOrigin;

            Node storage nodeToDelete = index.nodes[nodeId];

            if (nodeToDelete.id != id) {
                // The id does not exist in the tree.
                return;
            }

            if (nodeToDelete.left != 0x0 || nodeToDelete.right != 0x0) {
                // This node is not a leaf node and thus must replace itself in
                // it's tree by either the previous or next node.
                if (nodeToDelete.left != 0x0) {
                    // This node is guaranteed to not have a right child.
                    replacementNode = index.nodes[getPreviousNode(index, nodeToDelete.nodeId)];
                }
                else {
                    // This node is guaranteed to not have a left child.
                    replacementNode = index.nodes[getNextNode(index, nodeToDelete.nodeId)];
                }
                // The replacementNode is guaranteed to have a parent.
                parent = index.nodes[replacementNode.parent];

                // Keep note of the location that our tree rebalancing should
                // start at.
                rebalanceOrigin = replacementNode.nodeId;

                // Join the parent of the replacement node with any subtree of
                // the replacement node.  We can guarantee that the replacement
                // node has at most one subtree because of how getNextNode and
                // getPreviousNode are used.
                if (parent.left == replacementNode.nodeId) {
                    parent.left = replacementNode.right;
                    if (replacementNode.right != 0x0) {
                        child = index.nodes[replacementNode.right];
                        child.parent = parent.nodeId;
                    }
                }
                if (parent.right == replacementNode.nodeId) {
                    parent.right = replacementNode.left;
                    if (replacementNode.left != 0x0) {
                        child = index.nodes[replacementNode.left];
                        child.parent = parent.nodeId;
                    }
                }

                // Now we replace the nodeToDelete with the replacementNode.
                // This includes parent/child relationships for all of the
                // parent, the left child, and the right child.
                replacementNode.parent = nodeToDelete.parent;
                if (nodeToDelete.parent != 0x0) {
                    parent = index.nodes[nodeToDelete.parent];
                    if (parent.left == nodeToDelete.nodeId) {
                        parent.left = replacementNode.nodeId;
                    }
                    if (parent.right == nodeToDelete.nodeId) {
                        parent.right = replacementNode.nodeId;
                    }
                }
                else {
                    // If the node we are deleting is the root node so update
                    // the indexId to root node mapping.
                    index.root = replacementNode.nodeId;
                }

                replacementNode.left = nodeToDelete.left;
                if (nodeToDelete.left != 0x0) {
                    child = index.nodes[nodeToDelete.left];
                    child.parent = replacementNode.nodeId;
                }

                replacementNode.right = nodeToDelete.right;
                if (nodeToDelete.right != 0x0) {
                    child = index.nodes[nodeToDelete.right];
                    child.parent = replacementNode.nodeId;
                }
            }
            else if (nodeToDelete.parent != 0x0) {
                // The node being deleted is a leaf node so we only erase it's
                // parent linkage.
                parent = index.nodes[nodeToDelete.parent];

                if (parent.left == nodeToDelete.nodeId) {
                    parent.left = 0x0;
                }
                if (parent.right == nodeToDelete.nodeId) {
                    parent.right = 0x0;
                }

                // keep note of where the rebalancing should begin.
                rebalanceOrigin = parent.nodeId;
            }
            else {
                // This is both a leaf node and the root node, so we need to
                // unset the root node pointer.
                index.root = 0x0;
            }

            // Now we zero out all of the fields on the nodeToDelete.
            nodeToDelete.id = 0x0;
            nodeToDelete.nodeId = 0x0;
            nodeToDelete.indexId = 0x0;
            nodeToDelete.value = 0;
            nodeToDelete.parent = 0x0;
            nodeToDelete.left = 0x0;
            nodeToDelete.right = 0x0;

            // Walk back up the tree rebalancing
            if (rebalanceOrigin != 0x0) {
                _rebalanceTree(index, rebalanceOrigin);
            }
        }

        bytes2 constant GT = ">";
        bytes2 constant LT = "<";
        bytes2 constant GTE = ">=";
        bytes2 constant LTE = "<=";
        bytes2 constant EQ = "==";

        function _compare(int left, bytes2 operator, int right) internal returns (bool) {
            if (operator == GT) {
                return (left > right);
            }
            if (operator == LT) {
                return (left < right);
            }
            if (operator == GTE) {
                return (left >= right);
            }
            if (operator == LTE) {
                return (left <= right);
            }
            if (operator == EQ) {
                return (left == right);
            }

            // Invalid operator.
            throw;
        }

        function _getMaximum(Index storage index, bytes32 nodeId) internal returns (int) {
                Node storage currentNode = index.nodes[nodeId];

                while (true) {
                    if (currentNode.right == 0x0) {
                        return currentNode.value;
                    }
                    currentNode = index.nodes[currentNode.right];
                }
        }

        function _getMinimum(Index storage index, bytes32 nodeId) internal returns (int) {
                Node storage currentNode = index.nodes[nodeId];

                while (true) {
                    if (currentNode.left == 0x0) {
                        return currentNode.value;
                    }
                    currentNode = index.nodes[currentNode.left];
                }
        }

        /** @dev Query the index for the edge-most node that satisfies the
         *  given query.  For >, >=, and ==, this will be the left-most node
         *  that satisfies the comparison.  For < and <= this will be the
         *  right-most node that satisfies the comparison.
         */
        /// @param index The index that should be queried
        /** @param operator One of '>', '>=', '<', '<=', '==' to specify what
         *  type of comparison operator should be used.
         */
        function query(Index storage index, bytes2 operator, int value) public returns (bytes32) {
                bytes32 rootNodeId = index.root;

                if (rootNodeId == 0x0) {
                    // Empty tree.
                    return 0x0;
                }

                Node storage currentNode = index.nodes[rootNodeId];

                while (true) {
                    if (_compare(currentNode.value, operator, value)) {
                        // We have found a match but it might not be the
                        // *correct* match.
                        if ((operator == LT) || (operator == LTE)) {
                            // Need to keep traversing right until this is no
                            // longer true.
                            if (currentNode.right == 0x0) {
                                return currentNode.nodeId;
                            }
                            if (_compare(_getMinimum(index, currentNode.right), operator, value)) {
                                // There are still nodes to the right that
                                // match.
                                currentNode = index.nodes[currentNode.right];
                                continue;
                            }
                            return currentNode.nodeId;
                        }

                        if ((operator == GT) || (operator == GTE) || (operator == EQ)) {
                            // Need to keep traversing left until this is no
                            // longer true.
                            if (currentNode.left == 0x0) {
                                return currentNode.nodeId;
                            }
                            if (_compare(_getMaximum(index, currentNode.left), operator, value)) {
                                currentNode = index.nodes[currentNode.left];
                                continue;
                            }
                            return currentNode.nodeId;
                        }
                    }

                    if ((operator == LT) || (operator == LTE)) {
                        if (currentNode.left == 0x0) {
                            // There are no nodes that are less than the value
                            // so return null.
                            return 0x0;
                        }
                        currentNode = index.nodes[currentNode.left];
                        continue;
                    }

                    if ((operator == GT) || (operator == GTE)) {
                        if (currentNode.right == 0x0) {
                            // There are no nodes that are greater than the value
                            // so return null.
                            return 0x0;
                        }
                        currentNode = index.nodes[currentNode.right];
                        continue;
                    }

                    if (operator == EQ) {
                        if (currentNode.value < value) {
                            if (currentNode.right == 0x0) {
                                return 0x0;
                            }
                            currentNode = index.nodes[currentNode.right];
                            continue;
                        }

                        if (currentNode.value > value) {
                            if (currentNode.left == 0x0) {
                                return 0x0;
                            }
                            currentNode = index.nodes[currentNode.left];
                            continue;
                        }
                    }
                }
        }

        function _rebalanceTree(Index storage index, bytes32 nodeId) internal {
            // Trace back up rebalancing the tree and updating heights as
            // needed..
            Node storage currentNode = index.nodes[nodeId];

            while (true) {
                int balanceFactor = _getBalanceFactor(index, currentNode.nodeId);

                if (balanceFactor == 2) {
                    // Right rotation (tree is heavy on the left)
                    if (_getBalanceFactor(index, currentNode.left) == -1) {
                        // The subtree is leaning right so it need to be
                        // rotated left before the current node is rotated
                        // right.
                        _rotateLeft(index, currentNode.left);
                    }
                    _rotateRight(index, currentNode.nodeId);
                }

                if (balanceFactor == -2) {
                    // Left rotation (tree is heavy on the right)
                    if (_getBalanceFactor(index, currentNode.right) == 1) {
                        // The subtree is leaning left so it need to be
                        // rotated right before the current node is rotated
                        // left.
                        _rotateRight(index, currentNode.right);
                    }
                    _rotateLeft(index, currentNode.nodeId);
                }

                if ((-1 <= balanceFactor) && (balanceFactor <= 1)) {
                    _updateNodeHeight(index, currentNode.nodeId);
                }

                if (currentNode.parent == 0x0) {
                    // Reached the root which may be new due to tree
                    // rotation, so set it as the root and then break.
                    break;
                }

                currentNode = index.nodes[currentNode.parent];
            }
        }

        function _getBalanceFactor(Index storage index, bytes32 nodeId) internal returns (int) {
                Node storage node = index.nodes[nodeId];

                return int(index.nodes[node.left].height) - int(index.nodes[node.right].height);
        }

        function _updateNodeHeight(Index storage index, bytes32 nodeId) internal {
                Node storage node = index.nodes[nodeId];

                node.height = max(index.nodes[node.left].height, index.nodes[node.right].height) + 1;
        }

        function _rotateLeft(Index storage index, bytes32 nodeId) internal {
            Node storage originalRoot = index.nodes[nodeId];

            if (originalRoot.right == 0x0) {
                // Cannot rotate left if there is no right originalRoot to rotate into
                // place.
                throw;
            }

            // The right child is the new root, so it gets the original
            // `originalRoot.parent` as it's parent.
            Node storage newRoot = index.nodes[originalRoot.right];
            newRoot.parent = originalRoot.parent;

            // The original root needs to have it's right child nulled out.
            originalRoot.right = 0x0;

            if (originalRoot.parent != 0x0) {
                // If there is a parent node, it needs to now point downward at
                // the newRoot which is rotating into the place where `node` was.
                Node storage parent = index.nodes[originalRoot.parent];

                // figure out if we're a left or right child and have the
                // parent point to the new node.
                if (parent.left == originalRoot.nodeId) {
                    parent.left = newRoot.nodeId;
                }
                if (parent.right == originalRoot.nodeId) {
                    parent.right = newRoot.nodeId;
                }
            }

            if (newRoot.left != 0) {
                // If the new root had a left child, that moves to be the
                // new right child of the original root node
                Node storage leftChild = index.nodes[newRoot.left];
                originalRoot.right = leftChild.nodeId;
                leftChild.parent = originalRoot.nodeId;
            }

            // Update the newRoot's left node to point at the original node.
            originalRoot.parent = newRoot.nodeId;
            newRoot.left = originalRoot.nodeId;

            if (newRoot.parent == 0x0) {
                index.root = newRoot.nodeId;
            }

            // TODO: are both of these updates necessary?
            _updateNodeHeight(index, originalRoot.nodeId);
            _updateNodeHeight(index, newRoot.nodeId);
        }

        function _rotateRight(Index storage index, bytes32 nodeId) internal {
            Node storage originalRoot = index.nodes[nodeId];

            if (originalRoot.left == 0x0) {
                // Cannot rotate right if there is no left node to rotate into
                // place.
                throw;
            }

            // The left child is taking the place of node, so we update it's
            // parent to be the original parent of the node.
            Node storage newRoot = index.nodes[originalRoot.left];
            newRoot.parent = originalRoot.parent;

            // Null out the originalRoot.left
            originalRoot.left = 0x0;

            if (originalRoot.parent != 0x0) {
                // If the node has a parent, update the correct child to point
                // at the newRoot now.
                Node storage parent = index.nodes[originalRoot.parent];

                if (parent.left == originalRoot.nodeId) {
                    parent.left = newRoot.nodeId;
                }
                if (parent.right == originalRoot.nodeId) {
                    parent.right = newRoot.nodeId;
                }
            }

            if (newRoot.right != 0x0) {
                Node storage rightChild = index.nodes[newRoot.right];
                originalRoot.left = newRoot.right;
                rightChild.parent = originalRoot.nodeId;
            }

            // Update the new root's right node to point to the original node.
            originalRoot.parent = newRoot.nodeId;
            newRoot.right = originalRoot.nodeId;

            if (newRoot.parent == 0x0) {
                index.root = newRoot.nodeId;
            }

            // Recompute heights.
            _updateNodeHeight(index, originalRoot.nodeId);
            _updateNodeHeight(index, newRoot.nodeId);
        }
}

/// @title Grove - queryable indexes for ordered data.
/// @author Piper Merriam <pipermerriam@gmail.com>
contract Grove {
        /*
         *  Indexes for ordered data
         *
         *  Address: 0x8017f24a47c889b1ee80501ff84beb3c017edf0b
         */
        // Map index_id to index
        mapping (bytes32 => GroveLib.Index) index_lookup;

        // Map node_id to index_id.
        mapping (bytes32 => bytes32) node_to_index;

        /// @notice Computes the id for a Grove index which is sha3(owner, indexName)
        /// @param owner The address of the index owner.
        /// @param indexName The name of the index.
        function computeIndexId(address owner, bytes32 indexName) constant returns (bytes32) {
                return GroveLib.computeIndexId(owner, indexName);
        }

        /// @notice Computes the id for a node in a given Grove index which is sha3(indexId, id)
        /// @param indexId The id for the index the node belongs to.
        /// @param id The unique identifier for the data this node represents.
        function computeNodeId(bytes32 indexId, bytes32 id) constant returns (bytes32) {
                return GroveLib.computeNodeId(indexId, id);
        }

        /*
         *  Node getters
         */
        /// @notice Retrieves the name of an index.
        /// @param indexId The id of the index.
        function getIndexName(bytes32 indexId) constant returns (bytes32) {
            return index_lookup[indexId].name;
        }

        /// @notice Retrieves the id of the root node for this index.
        /// @param indexId The id of the index.
        function getIndexRoot(bytes32 indexId) constant returns (bytes32) {
            return index_lookup[indexId].root;
        }

        /// @dev Retrieve the unique identifier this node represents.
        /// @param nodeId The id for the node
        function getNodeId(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeId(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the index id for the node.
        /// @param nodeId The id for the node
        function getNodeIndexId(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeIndexId(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the value of the node.
        /// @param nodeId The id for the node
        function getNodeValue(bytes32 nodeId) constant returns (int) {
            return GroveLib.getNodeValue(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the height of the node.
        /// @param nodeId The id for the node
        function getNodeHeight(bytes32 nodeId) constant returns (uint) {
            return GroveLib.getNodeHeight(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the parent id of the node.
        /// @param nodeId The id for the node
        function getNodeParent(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeParent(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the left child id of the node.
        /// @param nodeId The id for the node
        function getNodeLeftChild(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeLeftChild(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /// @dev Retrieve the right child id of the node.
        /// @param nodeId The id for the node
        function getNodeRightChild(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNodeRightChild(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /** @dev Retrieve the id of the node that comes immediately before this
         *  one.  Returns 0x0 if there is no previous node.
         */
        /// @param nodeId The id for the node
        function getPreviousNode(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getPreviousNode(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /** @dev Retrieve the id of the node that comes immediately after this
         *  one.  Returns 0x0 if there is no previous node.
         */
        /// @param nodeId The id for the node
        function getNextNode(bytes32 nodeId) constant returns (bytes32) {
            return GroveLib.getNextNode(index_lookup[node_to_index[nodeId]], nodeId);
        }

        /** @dev Update or Insert a data element represented by the unique
         *  identifier `id` into the index.
         */
        /// @param indexName The human readable name for the index that the node should be upserted into.
        /// @param id The unique identifier that the index node represents.
        /// @param value The number which represents this data elements total ordering.
        function insert(bytes32 indexName, bytes32 id, int value) public {
                bytes32 indexId = computeIndexId(msg.sender, indexName);
                var index = index_lookup[indexId];

                if (index.name != indexName) {
                        // If this is a new index, store it's name and id
                        index.name = indexName;
                        index.id = indexId;
                }

                // Store the mapping from nodeId to the indexId
                node_to_index[computeNodeId(indexId, id)] = indexId;

                GroveLib.insert(index, id, value);
        }

        /// @dev Query whether a node exists within the specified index for the unique identifier.
        /// @param indexId The id for the index.
        /// @param id The unique identifier of the data element.
        function exists(bytes32 indexId, bytes32 id) constant returns (bool) {
            return GroveLib.exists(index_lookup[indexId], id);
        }

        /// @dev Remove the index node for the given unique identifier.
        /// @param indexName The name of the index.
        /// @param id The unique identifier of the data element.
        function remove(bytes32 indexName, bytes32 id) public {
            GroveLib.remove(index_lookup[computeIndexId(msg.sender, indexName)], id);
        }

        /** @dev Query the index for the edge-most node that satisfies the
         * given query.  For >, >=, and ==, this will be the left-most node
         * that satisfies the comparison.  For < and <= this will be the
         * right-most node that satisfies the comparison.
         */
        /// @param indexId The id of the index that should be queried
        /** @param operator One of '>', '>=', '<', '<=', '==' to specify what
         *  type of comparison operator should be used.
         */
        function query(bytes32 indexId, bytes2 operator, int value) public returns (bytes32) {
                return GroveLib.query(index_lookup[indexId], operator, value);
        }
}


Rename variable master to implementation #2 (#2553)

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../proxy/Clones.sol";
import "../utils/Address.sol";

contract ClonesMock {
    using Address for address;
    using Clones for address;

    event NewInstance(address instance);

    function clone(address implementation, bytes calldata initdata) public payable {
        _initAndEmit(implementation.clone(), initdata);
    }

    function cloneDeterministic(address implementation, bytes32 salt, bytes calldata initdata) public payable {
        _initAndEmit(implementation.cloneDeterministic(salt), initdata);
    }

    function predictDeterministicAddress(address implementation, bytes32 salt) public view returns (address predicted) {
        return implementation.predictDeterministicAddress(salt);
    }

    function _initAndEmit(address instance, bytes memory initdata) private {
        if (initdata.length > 0) {
            instance.functionCallWithValue(initdata, msg.value);
        }
        emit NewInstance(instance);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../proxy/Clones.sol";
import "../utils/Address.sol";

contract ClonesMock {
    using Address for address;
    using Clones for address;

    event NewInstance(address instance);

    function clone(address master, bytes calldata initdata) public payable {
        _initAndEmit(master.clone(), initdata);
    }

    function cloneDeterministic(address master, bytes32 salt, bytes calldata initdata) public payable {
        _initAndEmit(master.cloneDeterministic(salt), initdata);
    }

    function predictDeterministicAddress(address master, bytes32 salt) public view returns (address predicted) {
        return master.predictDeterministicAddress(salt);
    }

    function _initAndEmit(address instance, bytes memory initdata) private {
        if (initdata.length > 0) {
            instance.functionCallWithValue(initdata, msg.value);
        }
        emit NewInstance(instance);
    }
}


Collapse sale structure for registry

Collapse sale structure for registry


Create sortaRandom.sol

Create sortaRandom.sol

A logically correct, but partially untested random (ish) number generator with hashes

function sortaRandomGen() { // function to hash a bunch o' blocks to get a "sorta" random number (SECURITY UNTESTED)

  uint[10] blockHashes;

  uint currentBlock = block.number;
  uint kindaRandom; // integer to hold the final random variable
  uint sumHash; // integer to hold the sum of the hashes

  for(uint i = 0; i <= 10; i++) { // for loop to fill the blockHashes array

      blockHashes[i] = uint(block.blockhash(currentBlock)); // adds the integer of the current blocks's hash to the array
      currentBlock -= 1; // grabs the previous block

  }

  for(uint j = 0; j <= 10; j++) { // for loop to sum the hashes

      sumHash += blockHashes[j];
      sumHash = uint(sha3(sumHash));

  }

  uint kindaRandom = uint(sha3(sumHash));
  return kindaRandom;

error: pathspec 'app/contracts/sortaRandom.sol' did not match any file(s) known to git