Problem Definition
While working on #4937 I noticed that the rest api calls the token network's set_total_withdraw() in an asynchronous way. Thus unlike for other proxy calls any exceptions thrown inside the proxy are not handled.
EDIT: Read the issue to figure out why this is actually not the case but also why this is still problematic. Keeping the description of what I initially thought to be a bug below so that the train of though of how we came here is preserved.
|
try: |
|
self.raiden_api.set_total_channel_withdraw( |
|
registry_address, |
|
channel_state.token_address, |
|
channel_state.partner_state.address, |
|
total_withdraw, |
|
) |
|
except (NonexistingChannel, UnknownTokenAddress) as e: |
|
return api_error(errors=str(e), status_code=HTTPStatus.BAD_REQUEST) |
|
except (InsufficientFunds, WithdrawMismatch) as e: |
|
return api_error(errors=str(e), status_code=HTTPStatus.CONFLICT) |
|
|
Here the rest api calls the python api's set_total_channel_withdraw
|
self.raiden.withdraw( |
|
canonical_identifier=channel_state.canonical_identifier, total_withdraw=total_withdraw |
|
) |
|
|
|
waiting.wait_for_withdraw_complete( |
|
raiden=self.raiden, |
|
canonical_identifier=channel_state.canonical_identifier, |
|
total_withdraw=total_withdraw, |
|
retry_timeout=retry_timeout, |
|
) |
In there instead of calling the proxy directly what the code does is call raiden_service.withdraw()
|
def withdraw( |
|
self, canonical_identifier: CanonicalIdentifier, total_withdraw: WithdrawAmount |
|
) -> None: |
|
init_withdraw = ActionChannelWithdraw( |
|
canonical_identifier=canonical_identifier, total_withdraw=total_withdraw |
|
) |
|
|
|
self.handle_and_track_state_changes([init_withdraw]) |
Which as can be seen above creates an Action state change and adds it to the pending greenlets for processing.
|
def send_withdraw_request( |
|
channel_state: NettingChannelState, |
|
total_withdraw: WithdrawAmount, |
|
block_number: BlockNumber, |
|
pseudo_random_generator: random.Random, |
|
) -> List[Event]: |
|
events: List[Event] = list() |
|
|
|
if get_status(channel_state) not in CHANNEL_STATES_PRIOR_TO_CLOSED: |
|
return events |
|
|
|
nonce = get_next_nonce(channel_state.our_state) |
|
expiration = get_safe_initial_expiration( |
|
block_number=block_number, reveal_timeout=channel_state.reveal_timeout |
|
) |
|
withdraw_state = PendingWithdrawState( |
|
total_withdraw=total_withdraw, nonce=nonce, expiration=expiration |
|
) |
|
|
|
channel_state.our_state.nonce = nonce |
|
channel_state.our_state.withdraws_pending[withdraw_state.total_withdraw] = withdraw_state |
|
|
|
withdraw_event = SendWithdrawRequest( |
|
canonical_identifier=CanonicalIdentifier( |
|
chain_identifier=channel_state.chain_id, |
|
token_network_address=channel_state.token_network_address, |
|
channel_identifier=channel_state.identifier, |
|
), |
|
recipient=channel_state.partner_state.address, |
|
message_identifier=message_identifier_from_prng(pseudo_random_generator), |
|
total_withdraw=withdraw_state.total_withdraw, |
|
participant=channel_state.our_state.address, |
|
nonce=channel_state.our_state.nonce, |
|
expiration=withdraw_state.expiration, |
|
) |
|
|
|
events.append(withdraw_event) |
|
|
|
return events |
That results in processing the Action through the state machine and eventually generating a SendWithdrawRequest event as seen above.
This will send a WithdrawRequest to the partner .... wait for the confirmation ... process it ... and only during that processing will the proxy call be done. So the proxy's exceptions will not be seen.
Task
Figure out a way to do this properly and catch the exceptions.
|
@staticmethod |
|
def handle_contract_send_channelwithdraw( |
|
raiden: "RaidenService", channel_withdraw_event: ContractSendChannelWithdraw |
|
) -> None: |
|
withdraw_confirmation_data = pack_withdraw( |
|
canonical_identifier=channel_withdraw_event.canonical_identifier, |
|
participant=raiden.address, |
|
total_withdraw=channel_withdraw_event.total_withdraw, |
|
expiration_block=channel_withdraw_event.expiration, |
|
) |
|
our_signature = raiden.signer.sign(data=withdraw_confirmation_data) |
|
|
|
channel_proxy = raiden.chain.payment_channel( |
|
canonical_identifier=channel_withdraw_event.canonical_identifier |
|
) |
|
|
|
channel_proxy.set_total_withdraw( |
|
total_withdraw=channel_withdraw_event.total_withdraw, |
|
expiration_block=channel_withdraw_event.expiration, |
|
participant_signature=our_signature, |
|
partner_signature=channel_withdraw_event.partner_signature, |
|
block_identifier=channel_withdraw_event.triggered_by_block_hash, |
|
) |
Perhaps catch the exceptions in the handler of the ContractSendChannelWithdraw event?
Problem Definition
While working on #4937 I noticed that the rest api calls the token network's
set_total_withdraw()in an asynchronous way. Thus unlike for other proxy calls any exceptions thrown inside the proxy are not handled.EDIT: Read the issue to figure out why this is actually not the case but also why this is still problematic. Keeping the description of what I initially thought to be a bug below so that the train of though of how we came here is preserved.
raiden/raiden/api/rest.py
Lines 1154 to 1165 in 6983c90
Here the rest api calls the python api's
set_total_channel_withdrawraiden/raiden/api/python.py
Lines 555 to 564 in 6983c90
In there instead of calling the proxy directly what the code does is call
raiden_service.withdraw()raiden/raiden/raiden_service.py
Lines 1210 to 1217 in 6983c90
Which as can be seen above creates an Action state change and adds it to the pending greenlets for processing.
raiden/raiden/transfer/channel.py
Lines 1607 to 1645 in 6983c90
That results in processing the Action through the state machine and eventually generating a
SendWithdrawRequestevent as seen above.This will send a WithdrawRequest to the partner .... wait for the confirmation ... process it ... and only during that processing will the proxy call be done. So the proxy's exceptions will not be seen.
Task
Figure out a way to do this properly and catch the exceptions.
raiden/raiden/raiden_event_handler.py
Lines 360 to 382 in 6983c90
Perhaps catch the exceptions in the handler of the
ContractSendChannelWithdrawevent?