예제 #1
0
    def get_result(self, request: Request):
        address = request.operation[ADDRESS]
        from_seqno = request.operation.get(FROM_SEQNO)
        encoded_root_hash = state_roots_serializer.serialize(
            bytes(self.state.committedHeadHash))
        proof, rv = self.state.generate_state_proof_for_keys_with_prefix(
            address, serialize=True, get_value=True)
        multi_sig = self.database_manager.bls_store.get(encoded_root_hash)
        if multi_sig:
            encoded_proof = proof_nodes_serializer.serialize(proof)
            proof = {
                MULTI_SIGNATURE: multi_sig.as_dict(),
                ROOT_HASH: encoded_root_hash,
                PROOF_NODES: encoded_proof
            }
        else:
            proof = {}

        # The outputs need to be returned in sorted order since each node's reply should be same.
        # Since no of outputs can be large, a concious choice to not use `operator.attrgetter` on an
        # already constructed list was made
        outputs = SortedItems()
        for k, v in rv.items():
            addr, seq_no = TokenStaticHelper.parse_state_key(k.decode())
            amount = rlp_decode(v)[0]
            if not amount:
                continue
            outputs.add(Output(addr, int(seq_no), int(amount)))

        utxos = outputs.sorted_list
        next_seqno = None
        if from_seqno:
            idx = next((idx for utxo, idx in zip(utxos, range(len(utxos)))
                        if utxo.seqNo >= from_seqno), None)
            if idx:
                utxos = utxos[idx:]
            else:
                utxos = []
        if len(utxos) > UTXO_LIMIT:
            next_seqno = utxos[UTXO_LIMIT].seqNo
            utxos = utxos[:UTXO_LIMIT]

        result = {
            f.IDENTIFIER.nm: request.identifier,
            f.REQ_ID.nm: request.reqId,
            OUTPUTS: utxos
        }

        result.update(request.operation)
        if next_seqno:
            result[NEXT_SEQNO] = next_seqno
        if proof:
            res_sub = deepcopy(result)
            res_sub[STATE_PROOF] = proof
            if len(json.dumps(res_sub)) <= self._msg_limit:
                result = res_sub
        return result
예제 #2
0
 def get_fee_from_state(state,
                        fees_alias=None,
                        is_committed=False,
                        with_proof=False,
                        bls_store=None):
     fees = None
     proof = None
     try:
         fees_key = build_path_for_set_fees(alias=fees_alias)
         if with_proof:
             root_hash = state.committedHeadHash if is_committed else state.headHash
             proof, serz = state.generate_state_proof(
                 fees_key,
                 root=state.get_head_by_hash(root_hash),
                 serialize=True,
                 get_value=True)
             if serz:
                 serz = state.get_decoded(serz)
             encoded_root_hash = state_roots_serializer.serialize(
                 bytes(root_hash))
             multi_sig = bls_store.get(encoded_root_hash)
             if multi_sig:
                 encoded_proof = proof_nodes_serializer.serialize(proof)
                 proof = {
                     MULTI_SIGNATURE: multi_sig.as_dict(),
                     ROOT_HASH: encoded_root_hash,
                     PROOF_NODES: encoded_proof
                 }
             else:
                 proof = {}
         else:
             serz = state.get(fees_key, isCommitted=is_committed)
         if serz:
             fees = config_state_serializer.deserialize(serz)
     except KeyError:
         pass
     if with_proof:
         return fees, proof
     return fees
 def _bad_hash_serialized(self):
     return state_roots_serializer.serialize(self._bad_hash_unserialized())
class PP:
    plugin_data = {
        FEES: {
            FEE_TXNS_IN_BATCH: 1,
            f.STATE_ROOT.nm: state_roots_serializer.serialize(BLANK_ROOT),
            f.TXN_ROOT.nm: 'VNsWDU8rZ9Jz9NF',
        }
    }

    @staticmethod
    def fake_pp(ledger_id=DOMAIN_LEDGER_ID):
        params = create_pre_prepare_params(state_root=generate_state_root(),
                                           ledger_id=ledger_id)
        return PrePrepare(*params)

    @staticmethod
    def fake_pp_without_fees(three_phase_handler, ledger_id=DOMAIN_LEDGER_ID):
        pp = PP.fake_pp(ledger_id=ledger_id)
        pp_with_fees = three_phase_handler.add_to_pre_prepare(pp)
        return pp_with_fees

    @staticmethod
    def fake_pp_with_fees(monkeypatch, three_phase_handler):
        pp = PP.fake_pp()

        def mock_get_state_root(ledger_id):
            if ledger_id == TOKEN_LEDGER_ID:
                return PP.plugin_data[FEES][f.STATE_ROOT.nm]
            else:
                return 'Pulled state root from a different ledger than sovtoken'

        def mock_get_txn_root(ledger_id):
            if ledger_id == TOKEN_LEDGER_ID:
                return PP.plugin_data[FEES][f.TXN_ROOT.nm]
            else:
                return 'Pulled txn root from a different ledger than sovtoken'

        state_root_deserialized = state_roots_serializer.deserialize(
            PP.plugin_data[FEES][f.STATE_ROOT.nm])
        txn_root_deserialized = state_roots_serializer.deserialize(
            PP.plugin_data[FEES][f.TXN_ROOT.nm])

        monkeypatch.setattr(three_phase_handler.fees_tracker,
                            'fees_in_current_batch', 1)
        monkeypatch.setattr(
            three_phase_handler.master_replica._ordering_service,
            'get_state_root_hash', mock_get_state_root)
        monkeypatch.setattr(
            three_phase_handler.master_replica._ordering_service,
            'get_txn_root_hash', mock_get_txn_root)
        monkeypatch.setattr(three_phase_handler.token_state._trie, 'root_hash',
                            state_root_deserialized)
        monkeypatch.setattr(three_phase_handler.token_ledger,
                            'uncommittedRootHash', txn_root_deserialized)

        return three_phase_handler.add_to_pre_prepare(pp)

    @staticmethod
    def from_request(req, three_phase_handler):
        replica = three_phase_handler.master_replica
        args = [
            replica.instId, replica.viewNo, replica.lastPrePrepareSeqNo + 1,
            get_utc_epoch(), [req.digest],
            init_discarded(), req.digest, DOMAIN_LEDGER_ID,
            replica.stateRootHash(TOKEN_LEDGER_ID),
            replica.txnRootHash(TOKEN_LEDGER_ID), 0, True
        ]
        return PrePrepare(*args)