def deduct_fees(self, request, cons_time, ledger_id, seq_no, txn): txn_type = request.operation[TXN_TYPE] fees_key = "{}#{}".format(txn_type, seq_no) if txn_type != XFER_PUBLIC and FeesAuthorizer.has_fees(request): inputs, outputs, signatures = getattr(request, f.FEES.nm) # This is correct since FEES is changed from config ledger whose # transactions have no fees fees = FeesAuthorizer.calculate_fees_from_req( self.utxo_cache, request) sigs = {i[ADDRESS]: s for i, s in zip(inputs, signatures)} txn = { OPERATION: { TXN_TYPE: FEE_TXN, INPUTS: inputs, OUTPUTS: outputs, REF: self.get_ref_for_txn_fees(ledger_id, seq_no), FEES: fees, }, f.SIGS.nm: sigs, f.REQ_ID.nm: get_req_id(txn), f.PROTOCOL_VERSION.nm: 2, } txn = reqToTxn(txn) self.token_ledger.append_txns_metadata([txn], txn_time=cons_time) _, txns = self.token_ledger.appendTxns( [TokenReqHandler.transform_txn_for_ledger(txn)]) self.updateState(txns) self.fee_txns_in_current_batch += 1 self.deducted_fees[fees_key] = fees return txn
def fees_authorizer(fees): authorizer = FeesAuthorizer( config_state=PruningState(KeyValueStorageInMemory()), utxo_cache=UTXOCache(KeyValueStorageInMemory())) authorizer.calculate_fees_from_req = lambda *args, **kwargs: fees.get( NYM_FEES_ALIAS) return authorizer
def apply_request(self, request: Request, batch_ts, prev_result): txn_type = request.operation[TXN_TYPE] seq_no = get_seq_no(prev_result) cons_time = get_txn_time(prev_result) if FeesAuthorizer.has_fees(request): inputs, outputs, signatures = getattr(request, f.FEES.nm) # This is correct since FEES is changed from config ledger whose # transactions have no fees fees = FeesAuthorizer.calculate_fees_from_req( self.utxo_cache, request) sigs = {i[ADDRESS]: s for i, s in zip(inputs, signatures)} txn = { OPERATION: { TXN_TYPE: FEE_TXN, INPUTS: inputs, OUTPUTS: outputs, REF: self._get_ref_for_txn_fees(seq_no), FEES: fees, }, f.SIGS.nm: sigs, f.REQ_ID.nm: get_req_id(prev_result), f.PROTOCOL_VERSION.nm: 2, } txn = reqToTxn(txn) self.token_ledger.append_txns_metadata([txn], txn_time=cons_time) _, txns = self.token_ledger.appendTxns([txn]) self.update_token_state(txn, request) self._fees_tracker.fees_in_current_batch += 1 self._fees_tracker.add_deducted_fees(txn_type, seq_no, fees) return None, None, prev_result
def write_auth_req_validator(warv, helpers): fee_handler = helpers.node.get_fees_req_handler() fees_authorizer = FeesAuthorizer(config_state=warv.config_state, utxo_cache=fee_handler.utxo_cache) def _mocked_cpf(self, req, required_fees): return req.fees == required_fees, '' def _mocked_cffr(self, utxo_cache, request): return request.fees fees_authorizer.can_pay_fees = functools.partial(_mocked_cpf, fees_authorizer) fees_authorizer.calculate_fees_from_req = functools.partial(_mocked_cffr, fees_authorizer) warv.register_authorizer(fees_authorizer) return warv
def register_authentication(node): utxo_cache = node.db_manager.get_store(UTXO_CACHE_LABEL) token_authnr = node.clientAuthNr.get_authnr_by_type(TokenAuthNr) if not token_authnr: raise ImportError('sovtoken plugin should be loaded, ' # noqa 'authenticator not found') fees_authnr = FeesAuthNr(ACCEPTABLE_WRITE_TYPES_FEE, ACCEPTABLE_QUERY_TYPES_FEE, ACCEPTABLE_ACTION_TYPES_FEE, node.db_manager.idr_cache, token_authnr) node.clientAuthNr.register_authenticator(fees_authnr) fees_authorizer = FeesAuthorizer(config_state=node.getState(CONFIG_LEDGER_ID), utxo_cache=utxo_cache) node.write_req_validator.register_authorizer(fees_authorizer) return fees_authnr
def integrate_plugin_in_node(node): from sovtokenfees.client_authnr import FeesAuthNr from sovtokenfees.static_fee_req_handler import StaticFeesReqHandler from sovtokenfees.three_phase_commit_handling import \ ThreePhaseCommitHandler from sovtoken import TOKEN_LEDGER_ID from sovtoken.client_authnr import TokenAuthNr def postCatchupCompleteClb(origin_clb): if origin_clb: origin_clb() fees_req_handler.postCatchupCompleteClbk() node.write_req_validator.auth_map.update(sovtokenfees_auth_map) token_authnr = node.clientAuthNr.get_authnr_by_type(TokenAuthNr) if not token_authnr: raise ImportError('sovtoken plugin should be loaded, ' # noqa 'authenticator not found') token_req_handler = node.get_req_handler(ledger_id=TOKEN_LEDGER_ID) if not token_req_handler: raise ImportError('sovtoken plugin should be loaded, request ' # noqa 'handler not found') # `handle_xfer_public_txn` in `TokenReqHandler` checks if the sum of inputs match # exactly the sum of outputs. Since the check to match inputs and outputs is done # during fees handling the check is avoided in `TokenReqHandler` by monkeypatching # `handle_xfer_public_txn` to do nothing. token_req_handler.handle_xfer_public_txn = lambda _: None token_ledger = token_req_handler.ledger token_state = token_req_handler.state utxo_cache = token_req_handler.utxo_cache fees_authnr = FeesAuthNr(node.getState(DOMAIN_LEDGER_ID), token_authnr) fees_req_handler = StaticFeesReqHandler( node.configLedger, node.getState(CONFIG_LEDGER_ID), token_ledger, token_state, utxo_cache, node.getState(DOMAIN_LEDGER_ID), node.bls_bft.bls_store, node, node.write_req_validator, ts_store=node.getStateTsDbStorage()) origin_token_clb = node.ledgerManager.ledgerRegistry[ TOKEN_LEDGER_ID].postCatchupCompleteClbk node.ledgerManager.ledgerRegistry[TOKEN_LEDGER_ID].postCatchupCompleteClbk = \ functools.partial(postCatchupCompleteClb, origin_token_clb) origin_token_post_added_clb = node.ledgerManager.ledgerRegistry[ TOKEN_LEDGER_ID].postTxnAddedToLedgerClbk def filter_fees(ledger_id: int, txn: Any): origin_token_post_added_clb( ledger_id, txn, get_type(txn) != FeesTransactions.FEES.value) node.ledgerManager.ledgerRegistry[ TOKEN_LEDGER_ID].postTxnAddedToLedgerClbk = filter_fees node.clientAuthNr.register_authenticator(fees_authnr) node_config_req_handler = node.get_req_handler(ledger_id=CONFIG_LEDGER_ID) node.unregister_req_handler(node_config_req_handler, CONFIG_LEDGER_ID) node.register_req_handler(fees_req_handler, CONFIG_LEDGER_ID) fees_authorizer = FeesAuthorizer( config_state=node.getState(CONFIG_LEDGER_ID), utxo_cache=utxo_cache) node.write_req_validator.register_authorizer(fees_authorizer) node.register_hook(NodeHooks.PRE_SIG_VERIFICATION, fees_authnr.verify_signature) node.register_hook(NodeHooks.POST_REQUEST_APPLICATION, fees_req_handler.deduct_fees) node.register_hook(NodeHooks.POST_REQUEST_COMMIT, fees_req_handler.commit_fee_txns) node.register_hook(NodeHooks.POST_BATCH_CREATED, fees_req_handler.post_batch_created) node.register_hook(NodeHooks.POST_BATCH_REJECTED, fees_req_handler.post_batch_rejected) node.register_hook(NodeHooks.POST_BATCH_COMMITTED, fees_req_handler.post_batch_committed) node.register_hook(NodeHooks.POST_NODE_STOPPED, token_req_handler.on_node_stopping) three_pc_handler = ThreePhaseCommitHandler(node.master_replica, token_ledger, token_state, fees_req_handler) node.master_replica.register_hook(ReplicaHooks.CREATE_PPR, three_pc_handler.add_to_pre_prepare) node.master_replica.register_hook(ReplicaHooks.CREATE_PR, three_pc_handler.add_to_prepare) node.master_replica.register_hook(ReplicaHooks.CREATE_ORD, three_pc_handler.add_to_ordered) node.master_replica.register_hook(ReplicaHooks.APPLY_PPR, three_pc_handler.check_recvd_pre_prepare) return node
def fees_authorizer(fee_handler): return FeesAuthorizer(config_state=fee_handler.state, utxo_cache=fee_handler.utxo_cache)