bad param docs

bad param docs

// Grove v0.2

/// @title GroveLib - Library for queriable indexed ordered data.
/// @author PiperMerriam - <pipermerriam@gmail.com>
library GroveLib {
        /*
         *  Indexes for ordered data
         *
         *  Address: TODO
         */
        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: TODO
         */
        // 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: TODO
         */
        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: TODO
         */
        // 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 indexId The id for 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);
        }
}


Do not allow to transfer tokens to the same token contract

Closes https://github.com/raiden-network/raiden-token/issues/67

pragma solidity ^0.4.11;

import './ERC223ReceivingContract.sol';

/// @title Base Token contract - Functions to be implemented by token contracts.
contract Token {
    /*
     * Implements ERC 20 standard.
     * https://github.com/ethereum/EIPs/blob/f90864a3d2b2b45c4decf95efd26b3f0c276051a/EIPS/eip-20-token-standard.md
     * https://github.com/ethereum/EIPs/issues/20
     *
     *  Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
     *  https://github.com/ethereum/EIPs/issues/223
     */

    /*
     * This is a slight change to the ERC20 base standard.
     * function totalSupply() constant returns (uint256 supply);
     * is replaced with:
     * uint256 public totalSupply;
     * This automatically creates a getter function for the totalSupply.
     * This is moved to the base contract since public getter functions are not
     * currently recognised as an implementation of the matching abstract
     * function by the compiler.
     */
    uint256 public totalSupply;

    /*
     * ERC 20
     */
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    /*
     * ERC 223
     */
    function transfer(address _to, uint256 _value, bytes _data) returns (bool success);

    /*
     * Events
     */
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

/// @title Standard token contract - Standard token implementation.
contract StandardToken is Token {

    /*
     * Data structures
     */
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    /*
     * Public functions
     */
    /// @notice Send `_value` tokens to `_to` from `msg.sender`.
    /// @dev Transfers sender's tokens to a given address. Returns success.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != 0x0);
        require(_to != address(this));
        require(balances[msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[msg.sender] -= _value;
        balances[_to] += _value;

        Transfer(msg.sender, _to, _value);

        return true;
    }

    /// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
    /// tokenFallback if sender is a contract.
    /// @dev Function that is called when a user or another contract wants to transfer funds.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @param _data Data to be sent to tokenFallback
    /// @return Returns success of function call.
    function transfer(
        address _to,
        uint256 _value,
        bytes _data)
        public
        returns (bool)
    {
        require(transfer(_to, _value));

        uint codeLength;

        assembly {
            // Retrieve the size of the code on target address, this needs assembly.
            codeLength := extcodesize(_to)
        }

        if (codeLength > 0) {
            ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
            receiver.tokenFallback(msg.sender, _value, _data);
        }

        return true;
    }

    /// @notice Transfer `_value` tokens from `_from` to `_to` if `msg.sender` is allowed.
    /// @dev Allows for an approved third party to transfer tokens from one
    /// address to another. Returns success.
    /// @param _from Address from where tokens are withdrawn.
    /// @param _to Address to where tokens are sent.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transferFrom(address _from, address _to, uint256 _value)
        public
        returns (bool)
    {
        require(_from != 0x0);
        require(_to != 0x0);
        require(_to != address(this));
        require(balances[_from] >= _value);
        require(allowed[_from][msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;

        Transfer(_from, _to, _value);

        return true;
    }

    /// @notice Allows `_spender` to transfer `_value` tokens from `msg.sender` to any address.
    /// @dev Sets approved amount of tokens for spender. Returns success.
    /// @param _spender Address of allowed account.
    /// @param _value Number of approved tokens.
    /// @return Returns success of function call.
    function approve(address _spender, uint256 _value) public returns (bool) {
        require(_spender != 0x0);
        require(_value > 0);

        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /*
     * Read functions
     */
    /// @dev Returns number of allowed tokens that a spender can transfer in
    /// behalf of a token owner.
    /// @param _owner Address of token owner.
    /// @param _spender Address of token spender.
    /// @return Returns remaining allowance for spender.
    function allowance(address _owner, address _spender)
        constant
        public
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /// @dev Returns number of tokens owned by the given address.
    /// @param _owner Address of token owner.
    /// @return Returns balance of owner.
    function balanceOf(address _owner) constant public returns (uint256) {
        return balances[_owner];
    }
}

/// @title Custom Token
contract CustomToken is StandardToken {

    /*
     *  Terminology:
     *  1 token unit = Tei
     *  1 token = TKN = Tei * multiplier
     *  multiplier set from token's number of decimals (i.e. 10**decimals)
     */

    /*
     *  Token metadata
     */
    string constant public name = "The Token";
    string constant public symbol = "TKN";
    uint8 constant public decimals = 18;
    uint constant multiplier = 10**uint(decimals);

    address public owner;
    address public auction_address;

    event Deployed(
        address indexed _auction,
        uint indexed _total_supply,
        uint indexed _auction_supply
    );
    event Burnt(
        address indexed _receiver,
        uint indexed _num,
        uint indexed _total_supply
    );

    /*
     *  Public functions
     */
    /// @dev Contract constructor function sets dutch auction contract address
    /// and assigns all tokens to dutch auction.
    /// @param auction Address of dutch auction contract.
    /// @param initial_supply Number of initially provided token units (Tei).
    /// @param owners Array of addresses receiving preassigned tokens.
    /// @param tokens Array of preassigned token units (Tei).
    function CustomToken(
        address auction,
        uint initial_supply,
        address[] owners,
        uint[] tokens)
        public
    {
        // Auction address should not be null.
        require(auction != 0x0);
        require(owners.length == tokens.length);
        // Initial supply is in Tei
        require(initial_supply > multiplier);

        owner = msg.sender;
        auction_address = auction;

        // Total supply of Tei at deployment
        totalSupply = initial_supply;

        // Preallocate tokens to beneficiaries
        uint prealloc_tokens;
        for (uint i = 0; i < owners.length; i++) {
            // Address should not be null.
            require(owners[i] != 0x0);
            require(tokens[i] > 0);
            require(balances[owners[i]] + tokens[i] > balances[owners[i]]);
            require(prealloc_tokens + tokens[i] > prealloc_tokens);

            balances[owners[i]] += tokens[i];
            prealloc_tokens += tokens[i];
            Transfer(0, owners[i], tokens[i]);
        }

        balances[auction_address] = totalSupply - prealloc_tokens;
        Transfer(0, auction_address, balances[auction]);

        Deployed(auction_address, totalSupply, balances[auction]);

        assert(balances[auction_address] > 0);
        assert(balances[auction_address] < totalSupply);
        assert(totalSupply == balances[auction_address] + prealloc_tokens);
    }

    /// @notice Allows `msg.sender` to simply destroy `num` token units (Tei),
    /// without receiving the corresponding amount of ether. This means the total
    /// token supply will decrease.
    /// @dev Allows to destroy token units (Tei) without receiving the
    /// corresponding amount of ether.
    /// @param num Number of token units (Tei) to burn.
    function burn(uint num) public {
        require(num > 0);
        require(balances[msg.sender] >= num);
        require(totalSupply >= num);

        uint pre_balance = balances[msg.sender];

        balances[msg.sender] -= num;
        totalSupply -= num;
        Burnt(msg.sender, num, totalSupply);

        assert(balances[msg.sender] == pre_balance - num);
    }

}

pragma solidity ^0.4.11;

import './ERC223ReceivingContract.sol';

/// @title Base Token contract - Functions to be implemented by token contracts.
contract Token {
    /*
     * Implements ERC 20 standard.
     * https://github.com/ethereum/EIPs/blob/f90864a3d2b2b45c4decf95efd26b3f0c276051a/EIPS/eip-20-token-standard.md
     * https://github.com/ethereum/EIPs/issues/20
     *
     *  Added support for the ERC 223 "tokenFallback" method in a "transfer" function with a payload.
     *  https://github.com/ethereum/EIPs/issues/223
     */

    /*
     * This is a slight change to the ERC20 base standard.
     * function totalSupply() constant returns (uint256 supply);
     * is replaced with:
     * uint256 public totalSupply;
     * This automatically creates a getter function for the totalSupply.
     * This is moved to the base contract since public getter functions are not
     * currently recognised as an implementation of the matching abstract
     * function by the compiler.
     */
    uint256 public totalSupply;

    /*
     * ERC 20
     */
    function balanceOf(address _owner) constant returns (uint256 balance);
    function transfer(address _to, uint256 _value) returns (bool success);
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    function approve(address _spender, uint256 _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    /*
     * ERC 223
     */
    function transfer(address _to, uint256 _value, bytes _data) returns (bool success);

    /*
     * Events
     */
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

/// @title Standard token contract - Standard token implementation.
contract StandardToken is Token {

    /*
     * Data structures
     */
    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;

    /*
     * Public functions
     */
    /// @notice Send `_value` tokens to `_to` from `msg.sender`.
    /// @dev Transfers sender's tokens to a given address. Returns success.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transfer(address _to, uint256 _value) public returns (bool) {
        require(_to != 0x0);
        require(balances[msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[msg.sender] -= _value;
        balances[_to] += _value;

        Transfer(msg.sender, _to, _value);

        return true;
    }

    /// @notice Send `_value` tokens to `_to` from `msg.sender` and trigger
    /// tokenFallback if sender is a contract.
    /// @dev Function that is called when a user or another contract wants to transfer funds.
    /// @param _to Address of token receiver.
    /// @param _value Number of tokens to transfer.
    /// @param _data Data to be sent to tokenFallback
    /// @return Returns success of function call.
    function transfer(
        address _to,
        uint256 _value,
        bytes _data)
        public
        returns (bool)
    {
        require(transfer(_to, _value));

        uint codeLength;

        assembly {
            // Retrieve the size of the code on target address, this needs assembly.
            codeLength := extcodesize(_to)
        }

        if (codeLength > 0) {
            ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
            receiver.tokenFallback(msg.sender, _value, _data);
        }

        return true;
    }

    /// @notice Transfer `_value` tokens from `_from` to `_to` if `msg.sender` is allowed.
    /// @dev Allows for an approved third party to transfer tokens from one
    /// address to another. Returns success.
    /// @param _from Address from where tokens are withdrawn.
    /// @param _to Address to where tokens are sent.
    /// @param _value Number of tokens to transfer.
    /// @return Returns success of function call.
    function transferFrom(address _from, address _to, uint256 _value)
        public
        returns (bool)
    {
        require(_from != 0x0);
        require(_to != 0x0);
        require(balances[_from] >= _value);
        require(allowed[_from][msg.sender] >= _value);
        require(balances[_to] + _value >= balances[_to]);

        balances[_to] += _value;
        balances[_from] -= _value;
        allowed[_from][msg.sender] -= _value;

        Transfer(_from, _to, _value);

        return true;
    }

    /// @notice Allows `_spender` to transfer `_value` tokens from `msg.sender` to any address.
    /// @dev Sets approved amount of tokens for spender. Returns success.
    /// @param _spender Address of allowed account.
    /// @param _value Number of approved tokens.
    /// @return Returns success of function call.
    function approve(address _spender, uint256 _value) public returns (bool) {
        require(_spender != 0x0);
        require(_value > 0);

        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        return true;
    }

    /*
     * Read functions
     */
    /// @dev Returns number of allowed tokens that a spender can transfer in
    /// behalf of a token owner.
    /// @param _owner Address of token owner.
    /// @param _spender Address of token spender.
    /// @return Returns remaining allowance for spender.
    function allowance(address _owner, address _spender)
        constant
        public
        returns (uint256)
    {
        return allowed[_owner][_spender];
    }

    /// @dev Returns number of tokens owned by the given address.
    /// @param _owner Address of token owner.
    /// @return Returns balance of owner.
    function balanceOf(address _owner) constant public returns (uint256) {
        return balances[_owner];
    }
}

/// @title Custom Token
contract CustomToken is StandardToken {

    /*
     *  Terminology:
     *  1 token unit = Tei
     *  1 token = TKN = Tei * multiplier
     *  multiplier set from token's number of decimals (i.e. 10**decimals)
     */

    /*
     *  Token metadata
     */
    string constant public name = "The Token";
    string constant public symbol = "TKN";
    uint8 constant public decimals = 18;
    uint constant multiplier = 10**uint(decimals);

    address public owner;
    address public auction_address;

    event Deployed(
        address indexed _auction,
        uint indexed _total_supply,
        uint indexed _auction_supply
    );
    event Burnt(
        address indexed _receiver,
        uint indexed _num,
        uint indexed _total_supply
    );

    /*
     *  Public functions
     */
    /// @dev Contract constructor function sets dutch auction contract address
    /// and assigns all tokens to dutch auction.
    /// @param auction Address of dutch auction contract.
    /// @param initial_supply Number of initially provided token units (Tei).
    /// @param owners Array of addresses receiving preassigned tokens.
    /// @param tokens Array of preassigned token units (Tei).
    function CustomToken(
        address auction,
        uint initial_supply,
        address[] owners,
        uint[] tokens)
        public
    {
        // Auction address should not be null.
        require(auction != 0x0);
        require(owners.length == tokens.length);
        // Initial supply is in Tei
        require(initial_supply > multiplier);

        owner = msg.sender;
        auction_address = auction;

        // Total supply of Tei at deployment
        totalSupply = initial_supply;

        // Preallocate tokens to beneficiaries
        uint prealloc_tokens;
        for (uint i = 0; i < owners.length; i++) {
            // Address should not be null.
            require(owners[i] != 0x0);
            require(tokens[i] > 0);
            require(balances[owners[i]] + tokens[i] > balances[owners[i]]);
            require(prealloc_tokens + tokens[i] > prealloc_tokens);

            balances[owners[i]] += tokens[i];
            prealloc_tokens += tokens[i];
            Transfer(0, owners[i], tokens[i]);
        }

        balances[auction_address] = totalSupply - prealloc_tokens;
        Transfer(0, auction_address, balances[auction]);

        Deployed(auction_address, totalSupply, balances[auction]);

        assert(balances[auction_address] > 0);
        assert(balances[auction_address] < totalSupply);
        assert(totalSupply == balances[auction_address] + prealloc_tokens);
    }

    /// @notice Allows `msg.sender` to simply destroy `num` token units (Tei),
    /// without receiving the corresponding amount of ether. This means the total
    /// token supply will decrease.
    /// @dev Allows to destroy token units (Tei) without receiving the
    /// corresponding amount of ether.
    /// @param num Number of token units (Tei) to burn.
    function burn(uint num) public {
        require(num > 0);
        require(balances[msg.sender] >= num);
        require(totalSupply >= num);

        uint pre_balance = balances[msg.sender];

        balances[msg.sender] -= num;
        totalSupply -= num;
        Burnt(msg.sender, num, totalSupply);

        assert(balances[msg.sender] == pre_balance - num);
    }

}


adding a simple solidity token smart contract

contract MyToken{
  string public name;
  string public symbol;
  uint8 public decimals;

  mapping (address => uint256) public balanceOf;

  event Transfer(address indexed from, address indexed to, uint256 value);

  function MyToken(uint256 _supply, string _name, string _symbol, uint8 _decimals) {
    if (_supply == 0) _supply = 1000;
    balanceOf[msg.sender] = _supply;
    name = _name;
    symbol = _symbol;
    decimals = _decimals;
  }

  function transfer(address _to, uint256 _amount) {
    // TODO add a test if there is enough tokens in the sender account
    if (balanceOf[msg.sender] < _amount) throw;     // throw is cancelling the transaction and return the gas to the sender
    balanceOf[msg.sender] -= _amount;
    balanceOf[_to] += _amount;
    Transfer(msg.sender, _to, _amount);
  }
}

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


add token dao node

add token dao node

contract token {
    address public creator;
    string public symbol;
    string public name;
    uint public baseUnit;
    uint totalSupply;
    mapping (address => uint) public balanceOf;
    mapping (address => mapping(address => bool)) approveOf;
    mapping (address => mapping(address => bool)) approveOnceOf;
    mapping (address => mapping(address => uint)) approveOnceValueOf;

    modifier creatorCheck { if (msg.sender == creator) _ }

    /* Events */
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event AddressApproval(address indexed _address, address indexed _proxy, bool _result);
    event AddressApprovalOnce(address indexed _address, address indexed _proxy, uint256 _value);

    /*Initial */
    function token(string _s, string _n, uint _unit) {
        creator = msg.sender;
        symbol = _s;
        name = _n;
        baseUnit = _unit;
    }

    /* Creator functions */
    function getTotalSupply()  creatorCheck returns (uint supply) {
        return totalSupply;
    }

    function emission(uint _amount) creatorCheck returns(bool result) {
        if (balanceOf[creator] + _amount < balanceOf[creator]) {return false;}
        balanceOf[creator] += _amount;
        totalSupply += _amount;
        return true;
    }

    function burn(uint _amount) creatorCheck returns(bool result) {
        if (balanceOf[creator] < _amount) {return false;}
        if (balanceOf[creator] + _amount < balanceOf[creator]) {return false;}
        balanceOf[creator] -= _amount;
        totalSupply -= _amount;
        return true;
    }

    /* Agent function */

    function myBalance() returns (uint256 balance) {
        balance = balanceOf[msg.sender];
        return balance;
    }

    function transfer(address _to, uint _value) returns (bool result) {
        if (balanceOf[msg.sender] < _value) {return false;}
        if (balanceOf[msg.sender] + _value < balanceOf[msg.sender]) {return false;}
        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
        Transfer(msg.sender, _to, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint _value) returns (bool success) {
        if(approveOf[_from][msg.sender])
        {
            if (balanceOf[_from] < _value) {return false;}
            if (balanceOf[_from] + _value < balanceOf[_from]) {return false;}
            balanceOf[_from] -= _value;
            balanceOf[_to] += _value;
            Transfer(_from, _to, _value);
            return true;
        } else if(approveOnceOf[_from][msg.sender] && approveOnceValueOf[_from][msg.sender]<=_value) {
            if (balanceOf[_from] < _value) {return false;}
            if (balanceOf[_from] + _value < balanceOf[_from]) {return false;}
            balanceOf[_from] -= _value;
            balanceOf[_to] += _value;
            Transfer(_from, _to, _value);
            return true;
        }
    }

    function approve(address _address) returns (bool result) {
        approveOf[msg.sender][_address] = true;
        AddressApproval(_address, msg.sender, true);
        return true;
    }

    function unapprove(address _address) returns (bool result) {
        approveOf[msg.sender][_address] = false;
        return true;
    }

    function approveOnce(address _address, uint _maxValue) returns (bool result) {
        approveOnceOf[msg.sender][_address] = true;
        approveOnceValueOf[msg.sender][_address] = _maxValue;
        AddressApprovalOnce(_address, msg.sender, _maxValue);
        return true;
    }

    function unapproveOnce(address _address) returns (bool result) {
        approveOnceOf[msg.sender][_address] = false;
        approveOnceValueOf[msg.sender][_address] = 0;
        return true;
    }

    function isApprovedOnceFor(address _target, address _proxy) returns (uint maxValue) {
        maxValue = approveOnceValueOf[_target][_proxy];
        return maxValue;
    }

    function isApprovedFor(address _target, address _proxy) returns (bool result) {
        result = approveOnceOf[_target][_proxy];
        return result;
    }
}

error: pathspec 'dao_nodes/token.sol' did not match any file(s) known to git