function voteOnBounty(
        uint128 bountyGuid,
        uint256 votes,
        bool validBloom
    )
        external
        onlyArbiter
        whenNotPaused
    {
        Bounty storage bounty = bountiesByGuid[bountyGuid];
        Vote[] storage bountyVotes = votesByGuid[bountyGuid];

        
        require(bounty.author != address(0), "Bounty has not been initialized");
        
        require(bounty.expirationBlock.add(ASSERTION_REVEAL_WINDOW) <= block.number, "Reveal round is still active");
        
        require(bounty.expirationBlock.add(ASSERTION_REVEAL_WINDOW).add(arbiterVoteWindow) > block.number, "Voting round has closed");
        
        require(arbiterVoteRegistryByGuid[bountyGuid][msg.sender] == false, "Arbiter has already voted");

        Vote memory a = Vote(
            msg.sender,
            votes,
            validBloom
        );

        votesByGuid[bountyGuid].push(a);

        staking.recordBounty(msg.sender, bountyGuid, block.number);
        arbiterVoteRegistryByGuid[bountyGuid][msg.sender] = true;
        uint256 tempQuorumMask = 0;
        uint256 quorumCount = 0;
        mapping (uint256 => uint256) quorumVotes = quorumVotesByGuid[bountyGuid];
        for (uint256 i = 0; i < bounty.numArtifacts; i++) {

            if (bounty.quorumMask != 0 && (bounty.quorumMask & (1 << i) != 0)) {
                tempQuorumMask = tempQuorumMask.add(calculateMask(i, 1));
                quorumCount = quorumCount.add(1);
                continue;
            }

            if (votes & (1 << i) != 0) {
                quorumVotes[i] = quorumVotes[i].add(1);
            }

            uint256 benignVotes = bountyVotes.length.sub(quorumVotes[i]);
            uint256 maxBenignValue = arbiterCount.sub(quorumVotes[i]).mul(BENIGN_VOTE_COEFFICIENT);
            uint256 maxMalValue = arbiterCount.sub(benignVotes).mul(MALICIOUS_VOTE_COEFFICIENT);

            if (quorumVotes[i].mul(MALICIOUS_VOTE_COEFFICIENT) >= maxBenignValue || benignVotes.mul(BENIGN_VOTE_COEFFICIENT) > maxMalValue) {
                tempQuorumMask = tempQuorumMask.add(calculateMask(i, 1));
                quorumCount = quorumCount.add(1);
            }
        }

        
        bounty.quorumMask = tempQuorumMask;

        
        if ((bountyVotes.length == arbiterCount || quorumCount == bounty.numArtifacts) && !bounty.quorumReached)  {
            bounty.quorumReached = true;
            bounty.quorumBlock = block.number.sub(bountiesByGuid[bountyGuid].expirationBlock);
            emit QuorumReached(bountyGuid);
        }

        emit NewVote(bountyGuid, votes, bounty.numArtifacts, msg.sender);
    }