Browse Source

tumbler: restart waits for confirmation

master
Adam Gibson 9 years ago
parent
commit
081384ba23
No known key found for this signature in database
GPG Key ID: B3AE09F1E9A3197A
  1. 4
      jmclient/jmclient/schedule.py
  2. 4
      scripts/sample-schedule-for-testnet
  3. 39
      scripts/tumbler.py
  4. 6
      scripts/tumblerguide.md

4
jmclient/jmclient/schedule.py

@ -39,7 +39,9 @@ def get_schedule(filename):
makercount = int(makercount)
destaddr = destaddr.strip()
waittime = float(waittime)
completed = int(completed)
completed = completed.strip()
if not len(completed) == 64:
completed = int(completed)
except ValueError as e:
return (False, "Failed to parse schedule line: " + sl)
if destaddr != "INTERNAL":

4
scripts/sample-schedule-for-testnet

@ -20,8 +20,8 @@
#index 4: waittime: a decimal value in minutes to wait, after confirmation of this
# transaction, before continuing to the next.
#index 5: completion flag: 0 until the transaction is seen on the network, when it
# is changed to 1. This is particularly useful for the `--restart` feature of tumbler.
# is changed to the txid. This is particularly useful for the `--restart` feature
# of tumbler. Then changes to 1 when tx is confirmed.
#==========================
# 0 = not yet completed, otherwise completed
1, 110000000, 3, INTERNAL, 0, 0
0, 20000000, 2, mnsquzxrHXpFsZeL42qwbKdCP2y1esN3qw, 0, 0

39
scripts/tumbler.py

@ -23,6 +23,21 @@ from jmbase.support import get_log, debug_dump_object, get_password
from cli_options import get_tumbler_parser
log = get_log()
def restart_waiter(txid):
ctr = 0
log.info("Waiting for confirmation of last transaction: " + str(txid))
while True:
time.sleep(10)
ctr += 1
if not (ctr % 12):
log.debug("Still waiting for confirmation of last transaction ...")
res = jm_single().bc_interface.query_utxo_set(txid, includeconf=True)
if not res[0]:
continue
if res[0]['confirms'] > 0:
break
log.info("The last transaction is now in a block; continuing.")
def main():
#Prepare log file giving simplified information
#on progress of tumble.
@ -78,11 +93,24 @@ def main():
if not res:
print("Failed to load schedule, name: " + str(
options['schedulefile']))
print("Error was: " + str(schedule))
sys.exit(0)
#This removes all entries that are marked as done;
#assumes user has not edited by hand, and edits have only happened
#on tx completion.
schedule = [s for s in schedule if s[5] == 0]
#This removes all entries that are marked as done
schedule = [s for s in schedule if s[5] != 1]
if isinstance(schedule[0][5], str) and len(schedule[0][5]) == 64:
#ensure last transaction is confirmed before restart
tumble_log.info("WAITING TO RESTART...")
txid = schedule[0][5]
restart_waiter(txid + ":0") #add 0 index because all have it
#remove the already-done entry (this connects to the other TODO,
#probably better *not* to truncate the done-already txs from file,
#but simplest for now.
schedule = schedule[1:]
elif schedule[0][5] != 0:
print("Error: first schedule entry is invalid.")
sys.exit(0)
with open(os.path.join(logsdir, options['schedulefile']), "wb") as f:
f.write(schedule_to_text(schedule))
tumble_log.info("TUMBLE RESTARTING")
else:
#Create a new schedule from scratch
@ -116,7 +144,8 @@ def main():
#it only affects future (non-complete) transactions, so the final
#full record should always be accurate; but TUMBLE.log should be
#used for checking what actually happened.
taker.schedule[taker.schedule_index][5] = 1
completion_flag = 1 if not addtolog else taker.txid
taker.schedule[taker.schedule_index][5] = completion_flag
with open(os.path.join(logsdir, options['schedulefile']),
"wb") as f:
f.write(schedule_to_text(taker.schedule))

6
scripts/tumblerguide.md

@ -11,14 +11,14 @@ This document explains the delta to the operation of that script, which is almos
In this implementation, each coinjoin has an associated "schedule" of format like this:
```
[mixdepth, amount-in-satoshis, N-counterparties (requested), destination address, wait time in minutes, flag indicating completed/incomplete (1/0)]
[mixdepth, amount-in-satoshis, N-counterparties (requested), destination address, wait time in minutes, flag indicating incomplete/broadcast/completed (0/txid/1)]
```
`[]` here represents a Python list. It's recorded in files in a csv format (because in some cases users may edit). See [this](https://github.com/AdamISZ/joinmarket-clientserver/blob/master/scripts/sample-schedule-for-testnet) testnet sample given in the repo. A couple of extra notes on the format:
* the 4th entry, the destination address, can have special values "INTERNAL" and "addrask"; the former indicates that the coins are to be sent to the "next" mixdepth, modulo the maximum mixdepth. The latter is the same function as in the original implementation, i.e. it takes a destination from those provided by the user, either in the initial command line or on a prompt during the run.
* 0 amounts for the second entry indicate, as for command line flags, a sweep
* 0 amounts for the second entry indicate, as for command line flags, a sweep; decimals indicate mixdepth fractions (for tumbler)
For the `sendpayment.py` script, this schedule can indeed be simply written in a file and passed as a parameter (for this reason it's likely the tumbler and sendpayment scripts can merge in future).
@ -87,7 +87,7 @@ This is hardcoded currently to `20 * maker_timeout_sec`, the figure 20 being har
#### Restarts
In case of shutdown or crash, the `TUMBLE.schedule` file mentioned above will have an up-to-date record of which transactions in the schedule completed successfully; and you can find the txids, for convenience, in `TUMBLE.log` to sanity check (of course you may want to run `wallet-tool.py` also, which is fine). By restarting the tumbler script with the same parameters, but appending an additional parameter `--restart`, the script will continue the tumble from the first not-successfully-completed transaction and continue. If you used a custom name for `TUMBLE.schedule`, or renamed it afterwards, don't forget to also pass the parameter `--schedulefile` so it can be found; note that these files are always assumed to be in the `logs/` subdirectory of where you're running (so `scripts/logs` here). (A small technical note: on restart, the `TUMBLE.schedule` is truncated in that the txs that already completed will be removed, something that should probably change, but all the info is logged in `TUMBLE.log`, which you should use as your primary record of what happened and when).
In case of shutdown or crash, the `TUMBLE.schedule` file mentioned above will have an up-to-date record of which transactions in the schedule completed successfully; and you can find the txids, for convenience, in `TUMBLE.log` to sanity check (of course you may want to run `wallet-tool.py` also, which is fine). By restarting the tumbler script with the same parameters, but appending an additional parameter `--restart`, the script will continue the tumble from the first not-successfully-completed transaction and continue (it will wait for confirmations on the last transaction, if it's not yet in a block). If you used a custom name for `TUMBLE.schedule`, or renamed it afterwards, don't forget to also pass the parameter `--schedulefile` so it can be found; note that these files are always assumed to be in the `logs/` subdirectory of where you're running (so `scripts/logs` here). (A small technical note: on restart, the `TUMBLE.schedule` is truncated in that the txs that already completed will be removed, something that should probably change, but all the info is logged in `TUMBLE.log`, which you should use as your primary record of what happened and when).
Minor note, you could conceivably edit `TUMBLE.schedule` before restarting, but this would have to be considered "advanced" usage!

Loading…
Cancel
Save