Browse Source

Don't use honest_makers in case: mempool conflict

Prior to this commit, if a tumbler coinjoin negotiation
failed in Phase 2, then the retry as per the logic in
taker_utils.tumbler_taker_finished_update would always
attempt to retry the transaction with those counterparties
that returned valid !sig responses. However this ignored
the case that all the counterparties responded validly,
but there was a mempool conflict in the created transaction.
After this commit, if it is detected that all counterparties
responded, it is assumed that a mempool conflict or similar
occurred with the transaction, and therefore it is better
to fallback to a schedule tweak and choose randomly again,
not to fix the counterparty set (which is likely to result
in failing again).
master
Adam Gibson 6 years ago
parent
commit
4af9c422a4
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 77
      jmclient/jmclient/taker_utils.py

77
jmclient/jmclient/taker_utils.py

@ -250,46 +250,55 @@ def tumbler_taker_finished_update(taker, schedulefile, tumble_log, options,
tumble_log.info(waiting_message) tumble_log.info(waiting_message)
log.info(waiting_message) log.info(waiting_message)
else: else:
#a transaction failed, either because insufficient makers # a transaction failed, either because insufficient makers
#(acording to minimum_makers) responded in Phase 1, or not all # (acording to minimum_makers) responded in Phase 1, or not all
#makers responded in Phase 2. We'll first try to repeat without the # makers responded in Phase 2, or the tx was a mempool conflict.
#troublemakers. # If the tx was a mempool conflict, we should restart with random
# maker choice as usual. If someone didn't respond, we'll try to
# repeat without the troublemakers.
log.info("Schedule entry: " + str( log.info("Schedule entry: " + str(
taker.schedule[taker.schedule_index]) + \ taker.schedule[taker.schedule_index]) + \
" failed after timeout, trying again") " failed after timeout, trying again")
taker.add_ignored_makers(taker.nonrespondants) taker.add_ignored_makers(taker.nonrespondants)
#Is the failure in Phase 2? #Is the failure in Phase 2?
if not taker.latest_tx is None: if not taker.latest_tx is None:
#Now we have to set the specific group we want to use, and hopefully if len(taker.nonrespondants) == 0:
#they will respond again as they showed honesty last time. # transaction was created validly but conflicted in the
#Note that we must wipe the list first; other honest makers needn't # mempool; just try again without honest settings;
#have the right settings (e.g. max cjamount), so can't be carried # i.e. fallback to same as Phase 1 failure.
#over from earlier transactions. log.info("Invalid transaction; possible mempool conflict.")
taker.honest_makers = [] else:
taker.add_honest_makers(list(set( #Now we have to set the specific group we want to use, and hopefully
taker.maker_utxo_data.keys()).symmetric_difference( #they will respond again as they showed honesty last time.
set(taker.nonrespondants)))) #Note that we must wipe the list first; other honest makers needn't
#If insufficient makers were honest, we can only tweak the schedule. #have the right settings (e.g. max cjamount), so can't be carried
#If enough were, we prefer the restart with them only: #over from earlier transactions.
log.info("Inside a Phase 2 failure; number of honest respondants was: " + str(len(taker.honest_makers))) taker.honest_makers = []
log.info("They were: " + str(taker.honest_makers)) taker.add_honest_makers(list(set(
if len(taker.honest_makers) >= jm_single().config.getint( taker.maker_utxo_data.keys()).symmetric_difference(
"POLICY", "minimum_makers"): set(taker.nonrespondants))))
tumble_log.info("Transaction attempt failed, attempting to " #If insufficient makers were honest, we can only tweak the schedule.
"restart with subset.") #If enough were, we prefer to restart with them only:
tumble_log.info("The paramaters of the failed attempt: ") log.info("Inside a Phase 2 failure; number of honest "
tumble_log.info(str(taker.schedule[taker.schedule_index])) "respondants was: " + str(len(taker.honest_makers)))
#we must reset the number of counterparties, as well as fix who they log.info("They were: " + str(taker.honest_makers))
#are; this is because the number is used to e.g. calculate fees. if len(taker.honest_makers) >= jm_single().config.getint(
#cleanest way is to reset the number in the schedule before restart. "POLICY", "minimum_makers"):
taker.schedule[taker.schedule_index][2] = len(taker.honest_makers) tumble_log.info("Transaction attempt failed, attempting to "
retry_str = "Retrying with: " + str(taker.schedule[ "restart with subset.")
taker.schedule_index][2]) + " counterparties." tumble_log.info("The paramaters of the failed attempt: ")
tumble_log.info(retry_str) tumble_log.info(str(taker.schedule[taker.schedule_index]))
log.info(retry_str) #we must reset the number of counterparties, as well as fix who they
taker.set_honest_only(True) #are; this is because the number is used to e.g. calculate fees.
taker.schedule_index -= 1 #cleanest way is to reset the number in the schedule before restart.
return taker.schedule[taker.schedule_index][2] = len(taker.honest_makers)
retry_str = "Retrying with: " + str(taker.schedule[
taker.schedule_index][2]) + " counterparties."
tumble_log.info(retry_str)
log.info(retry_str)
taker.set_honest_only(True)
taker.schedule_index -= 1
return
#There were not enough honest counterparties. #There were not enough honest counterparties.
#Tumbler is aggressive in trying to complete; we tweak the schedule #Tumbler is aggressive in trying to complete; we tweak the schedule

Loading…
Cancel
Save