Ejemplo n.º 1
0
    def _apply_proposal(self, public_key, proposal_data, context):
        """Propose a new unit.

        If the threshold requires more than 1 vote then queue the
        proposal in candidates, otherwise write the unit to the
        chain
        """
        unit_proposal = UnitProposal()
        unit_proposal.ParseFromString(proposal_data)
        unit = Unit()
        unit.ParseFromString(unit_proposal.unit)

        proposal_id = self.unit_address(unit)
        approval_threshold = self._get_approval_threshold(context)
        if approval_threshold > 1:
            unit_candidates = self._get_candidates(context)
            existing_candidate = _first(
                unit_candidates.candidates,
                lambda candidate: candidate.proposal_id == proposal_id)

            if existing_candidate is not None:
                raise InvalidTransaction('Duplicate proposal for {}'.format(
                    unit_proposal.type))

            record = UnitCandidate.VoteRecord(
                public_key=public_key,
                vote=UnitCandidate.VoteRecord.VOTE_ACCEPT)
            unit_candidates.candidates.add(proposal_id=proposal_id,
                                           proposal=unit_proposal,
                                           votes=[record])
            self._set_candidates(context, unit_candidates)
        else:
            _set_unit_data(context, proposal_id, unit)
            LOGGER.debug('Set unit {}'.format(unit))
Ejemplo n.º 2
0
    def _apply_proposal(self, auth_keys, public_key, units_proposal_data,
                        context):
        units_proposal = UnitProposal()
        units_proposal.ParseFromString(units_proposal_data)

        proposal_id = hashlib.sha256(units_proposal_data).hexdigest()

        approval_threshold = _get_approval_threshold(context)

        _validate_units(auth_keys, units_proposal.code, units_proposal.value)

        if approval_threshold > 1:
            units_candidates = _get_units_candidates(context)

            existing_candidate = _first(
                units_candidates.candidates,
                lambda candidate: candidate.proposal_id == proposal_id)

            if existing_candidate is not None:
                raise InvalidTransaction('Duplicate proposal for {}'.format(
                    units_proposal.code))

            record = UnitCandidate.VoteRecord(public_key=public_key,
                                              vote=UnitVote.ACCEPT)
            units_candidates.candidates.add(proposal_id=proposal_id,
                                            proposal=units_proposal,
                                            votes=[record])

            LOGGER.debug('Proposal made to set %s to %s', units_proposal.code,
                         units_proposal.value)
            _save_units_candidates(context, units_candidates)
        else:
            _set_units_value(context, units_proposal.code,
                             units_proposal.value)
Ejemplo n.º 3
0
    def test_propose(self):
        """
        Tests proposing a value in ballot mode.
        """
        self._propose('my.config.unit', 'myvalue')

        self._expect_get('hashblock.units.vote.authorized_keys',
                         self._public_key)
        self._expect_get('hashblock.units.vote.approval_threshold', '2')
        self._expect_get('hashblock.units.vote.proposals')

        proposal = UnitProposal(code='my.config.unit',
                                value='myvalue',
                                nonce='somenonce')
        proposal_id = _to_hash(proposal.SerializeToString())
        record = UnitCandidate.VoteRecord(public_key=self._public_key,
                                          vote=UnitVote.ACCEPT)
        candidate = UnitCandidate(proposal_id=proposal_id,
                                  proposal=proposal,
                                  votes=[record])

        candidates = UnitCandidates(candidates=[candidate])

        # Get's again to update the entry
        self._expect_get('hashblock.units.vote.proposals')
        self._expect_set('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))

        self._expect_add_event('hashblock.units.vote.proposals')

        self._expect_ok()
Ejemplo n.º 4
0
    def test_vote_counted(self):
        """
        Tests voting on a given unit, where the vote is counted only.
        """
        proposal = UnitProposal(code='my.config.unit',
                                value='myvalue',
                                nonce='somenonce')
        proposal_id = _to_hash(proposal.SerializeToString())
        record = UnitCandidate.VoteRecord(public_key="some_other_public_key",
                                          vote=UnitVote.ACCEPT)
        candidate = UnitCandidate(proposal_id=proposal_id,
                                  proposal=proposal,
                                  votes=[record])

        candidates = UnitCandidates(candidates=[candidate])

        self._vote(proposal_id, 'my.config.unit', UnitVote.ACCEPT)

        self._expect_get(
            'hashblock.units.vote.authorized_keys',
            self._public_key + ',some_other_public_key,third_public_key')
        self._expect_get('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))
        self._expect_get('hashblock.units.vote.approval_threshold', '3')

        # expect to update the proposals
        self._expect_get('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))

        record = UnitCandidate.VoteRecord(public_key="some_other_public_key",
                                          vote=UnitVote.ACCEPT)
        new_record = UnitCandidate.VoteRecord(public_key=self._public_key,
                                              vote=UnitVote.ACCEPT)
        candidate = UnitCandidate(proposal_id=proposal_id,
                                  proposal=proposal,
                                  votes=[record, new_record])

        updated_candidates = UnitCandidates(candidates=[candidate])
        self._expect_set(
            'hashblock.units.vote.proposals',
            base64.b64encode(updated_candidates.SerializeToString()))

        self._expect_add_event('hashblock.units.vote.proposals')

        self._expect_ok()
Ejemplo n.º 5
0
    def test_vote_approved(self):
        """
        Tests voting on a given unit, where the unit is approved
        """
        proposal = UnitProposal(code='my.config.unit',
                                value='myvalue',
                                nonce='somenonce')
        proposal_id = _to_hash(proposal.SerializeToString())
        record = UnitCandidate.VoteRecord(public_key="some_other_public_key",
                                          vote=UnitVote.ACCEPT)
        candidate = UnitCandidate(proposal_id=proposal_id,
                                  proposal=proposal,
                                  votes=[record])

        candidates = UnitCandidates(candidates=[candidate])

        self._vote(proposal_id, 'my.config.unit', UnitVote.ACCEPT)

        self._expect_get('hashblock.units.vote.authorized_keys',
                         self._public_key + ',some_other_public_key')
        self._expect_get('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))
        self._expect_get('hashblock.units.vote.approval_threshold', '2')

        # the vote should pass
        self._expect_get('my.config.unit')
        self._expect_set('my.config.unit', 'myvalue')

        self._expect_add_event("my.config.unit")

        # expect to update the proposals
        self._expect_get('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))
        self._expect_set('hashblock.units.vote.proposals',
                         base64.b64encode(EMPTY_CANDIDATES))

        self._expect_add_event('hashblock.units.vote.proposals')

        self._expect_ok()
Ejemplo n.º 6
0
    def test_vote_rejects_a_tie(self):
        """
        Tests voting on a given unit, where there is a tie for accept and
        for reject, with no remaining auth keys.
        """
        proposal = UnitProposal(code='my.config.unit',
                                value='myvalue',
                                nonce='somenonce')
        proposal_id = _to_hash(proposal.SerializeToString())
        candidate = UnitCandidate(proposal_id=proposal_id,
                                  proposal=proposal,
                                  votes=[
                                      UnitCandidate.VoteRecord(
                                          public_key='some_other_public_key',
                                          vote=UnitVote.ACCEPT),
                                  ])

        candidates = UnitCandidates(candidates=[candidate])

        self._vote(proposal_id, 'my.config.unit', UnitVote.REJECT)

        self._expect_get('hashblock.units.vote.authorized_keys',
                         self._public_key + ',some_other_public_key')
        self._expect_get('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))
        self._expect_get('hashblock.units.vote.approval_threshold', '2')

        # expect to update the proposals
        self._expect_get('hashblock.units.vote.proposals',
                         base64.b64encode(candidates.SerializeToString()))
        self._expect_set('hashblock.units.vote.proposals',
                         base64.b64encode(EMPTY_CANDIDATES))

        self._expect_add_event('hashblock.units.vote.proposals')

        self._expect_ok()
Ejemplo n.º 7
0
    def create_proposal_transaction(self, code, value, nonce):
        proposal = UnitProposal(code=code, value=value, nonce=nonce)
        payload = UnitPayload(action=UnitPayload.PROPOSE,
                              data=proposal.SerializeToString())

        return self._create_tp_process_request(code, payload)