Skip to content

Commit 530167a

Browse files
authored
Merge pull request #142 from devin-fisher/fix_TOK_387-2
don't allow multiple outputs on TXN fees
2 parents 5d5ba44 + b11bdeb commit 530167a

5 files changed

Lines changed: 78 additions & 13 deletions

File tree

sovtoken/sovtoken/test/helpers/helper_request.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22

3-
from indy.ledger import build_nym_request
3+
from indy.ledger import build_nym_request, build_schema_request
44
from plenum.common.constants import TXN_TYPE, CURRENT_PROTOCOL_VERSION, GET_TXN, DATA
55
from plenum.common.request import Request
66
from plenum.common.types import f
@@ -104,8 +104,7 @@ def nym(
104104
sdk_wallet=None,
105105
):
106106
""" Builds a nym request. """
107-
sdk_wallet = sdk_wallet or self._steward_wallet
108-
_, sdk_wallet_did = sdk_wallet
107+
sdk_wallet_did = self._find_wallet_did(sdk_wallet)
109108

110109
if not dest:
111110
(dest, new_verkey) = self._wallet.create_did(
@@ -129,6 +128,23 @@ def nym(
129128

130129
return request
131130

131+
def schema(
132+
self,
133+
schema_data,
134+
sdk_wallet=None
135+
):
136+
sdk_wallet_did = self._find_wallet_did(sdk_wallet)
137+
schema_request_future = build_schema_request(sdk_wallet_did, schema_data)
138+
schema_request = self._looper.loop.run_until_complete(schema_request_future)
139+
request = self._sdk.sdk_json_to_request_object(json.loads(schema_request))
140+
request = self._sign_sdk(request, sdk_wallet=sdk_wallet)
141+
return request
142+
143+
def _find_wallet_did(self, sdk_wallet):
144+
sdk_wallet = sdk_wallet or self._steward_wallet
145+
_, sdk_wallet_did = sdk_wallet
146+
return sdk_wallet_did
147+
132148
def payment_signatures(self, inputs, outputs):
133149
""" Generate a list of payment signatures from inptus and outputs. """
134150
signatures = []

sovtoken/sovtoken/token_req_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ def validate_given_inputs_outputs(inputs_sum, outputs_sum, required_amount, requ
8787
if inputs_sum == required_amount:
8888
return # Equal is valid
8989
elif inputs_sum > required_amount:
90-
error = 'Extra funds, sum of inputs is {}' \
91-
'but required amount is {}. sum of outputs: {}'.format(inputs_sum, required_amount, outputs_sum)
90+
error = 'Extra funds, sum of inputs is {} ' \
91+
'but required amount: {} -- sum of outputs: {}'.format(inputs_sum, required_amount, outputs_sum)
9292
if error_msg_suffix and isinstance(error_msg_suffix, str):
9393
error += ' ' + error_msg_suffix
9494
raise ExtraFundsError(getattr(request, f.IDENTIFIER.nm, None),

sovtokenfees/sovtokenfees/static_fee_req_handler.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
logger = getlogger()
3232

33+
MAX_FEE_OUTPUTS = 1
34+
3335

3436
class StaticFeesReqHandler(FeeReqHandler):
3537
valid_txn_types = {SET_FEES, GET_FEES, FEE_TXN}
@@ -95,6 +97,15 @@ def can_pay_fees(self, request):
9597
self._get_deducted_fees_xfer(request, required_fees)
9698
self.deducted_fees_xfer[request.key] = required_fees
9799
elif required_fees:
100+
# We don't want to allow transfers on txn fees. So only one OUTPUT address can be used.
101+
# We could consider lock this down even more by requiring OUTPUT address to be one of the
102+
# INPUT address
103+
outputs = request.fees[1]
104+
if len(outputs) > MAX_FEE_OUTPUTS:
105+
raise InvalidClientRequest(request.identifier,
106+
request.reqId,
107+
"Only {} OUTPUT is allow for Transaction fees".format(MAX_FEE_OUTPUTS))
108+
98109
self._get_deducted_fees_non_xfer(request, required_fees)
99110

100111
# TODO: Fix this to match signature of `FeeReqHandler` and extract
@@ -144,12 +155,12 @@ def doStaticValidation(self, request: Request):
144155
else:
145156
super().doStaticValidation(request)
146157

147-
def validate(self, req: Request):
148-
operation = req.operation
158+
def validate(self, request: Request):
159+
operation = request.operation
149160
if operation[TXN_TYPE] == SET_FEES:
150-
validate_multi_sig_txn(req, TRUSTEE, self.domain_state, self.MinSendersForFees)
161+
validate_multi_sig_txn(request, TRUSTEE, self.domain_state, self.MinSendersForFees)
151162
else:
152-
super().validate(req)
163+
super().validate(request)
153164

154165
def get_query_response(self, request: Request):
155166
return self.query_handlers[request.operation[TXN_TYPE]](request)
@@ -307,8 +318,8 @@ def _handle_incorrect_funds(sum_inputs, sum_outputs, expected_amount, required_f
307318
raise InsufficientFundsError(request.identifier, request.reqId, error)
308319
if sum_inputs > expected_amount:
309320
error = 'Extra funds, sum of inputs is {} ' \
310-
'but required is {} (sum of outputs: {}, ' \
311-
'fees: {})'.format(sum_inputs, expected_amount, sum_outputs, required_fees)
321+
'but required is: {} -- sum of outputs: {} ' \
322+
'-- fees: {})'.format(sum_inputs, expected_amount, sum_outputs, required_fees)
312323
raise ExtraFundsError(request.identifier, request.reqId, error)
313324

314325
@staticmethod

sovtokenfees/sovtokenfees/test/helpers/helper_request.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
from sovtokenfees.constants import SET_FEES, FEES, GET_FEES
55
from sovtoken.constants import AMOUNT, ADDRESS
66

7+
from stp_core.common.log import getlogger
8+
9+
logger = getlogger()
710

811
class HelperRequest(token_helper_request.HelperRequest):
912
"""
@@ -56,10 +59,21 @@ def add_fees(
5659
change = total_inputs - fee_amount
5760

5861
if change > 0 and change_address:
59-
outputs = [{ADDRESS: change_address, AMOUNT: change}]
62+
if not isinstance(change_address, list):
63+
change_address = [change_address]
64+
change_part = change // len(change_address)
65+
if change_part <= 0:
66+
raise Exception("Unable to divide {}, {} ways".format(change, len(change_address)))
67+
change_mod = change % len(change_address)
68+
outputs = []
69+
for address in change_address:
70+
outputs.append({ADDRESS: address, AMOUNT: change_part+change_mod})
71+
change_mod = 0 # Only add remainder once
6072
else:
6173
outputs = []
6274

75+
logger.info("*"*20)
76+
logger.info(str(outputs))
6377
fees_signatures = self.fees_signatures(inputs, outputs, request.digest)
6478

6579
inputs = self._prepare_inputs(inputs)

sovtokenfees/sovtokenfees/test/test_fees_non_xfer_txn.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from plenum.common.exceptions import RequestRejectedException, RequestNackedException
66
from plenum.common.txn_util import get_seq_no, get_payload_data, get_txn_time
77
from plenum.common.types import f
8-
from plenum.test.pool_transactions.helper import sdk_build_get_txn_request
8+
9+
from sovtoken.test.wallet import Address
910
from sovtokenfees.constants import FEES, REF
1011
from sovtoken import TOKEN_LEDGER_ID
1112
from sovtoken.constants import INPUTS, OUTPUTS, AMOUNT, ADDRESS, SEQNO
@@ -130,6 +131,29 @@ def test_fees_larger(
130131
helpers.sdk.send_and_check_request_objects([req])
131132

132133

134+
def test_fees_too_many_outputs(
135+
helpers,
136+
fees_set,
137+
address_main,
138+
mint_tokens,
139+
):
140+
"""
141+
More than one output adress
142+
"""
143+
req = helpers.request.nym()
144+
fee_amount = fees_set[FEES][req.operation[TXN_TYPE]]
145+
utxos = helpers.general.get_utxo_addresses([address_main])[0]
146+
helpers.request.add_fees(
147+
req,
148+
utxos,
149+
fee_amount,
150+
change_address=[address_main, Address().address]
151+
)
152+
with pytest.raises(RequestRejectedException):
153+
helpers.sdk.send_and_check_request_objects([req])
154+
155+
156+
133157
def test_fees_incorrect_sig(
134158
helpers,
135159
fees_set,

0 commit comments

Comments
 (0)