Browse Source

Several tweaks for bech32 orderbook, plus docs

* yg scripts set reloffer/absoffer only:

Prior to this commit, the yield generator user
level scripts required the user to specify offer
types depending on the wallet, but only 'rel/abs'
distinction is user choice; the other element
(native segwit, p2sh or p2pkh) must be defined
by the wallet, so we now call `wallet.get_txtype()`
to translate from reloffer/absoffer to sw0.. etc.

* Taker chooses nversion, nlocktime per wallet type:

Takers who are still using p2sh-p2wpkh wallets will
not want to flag their transactions with different
tx metadata than previous versions that are still
running, so we check the `get_txtype()` output to
decide which nVersion and nLockTime to use.
Also, the SNICKER locktime is reverted to zero as
according to draft spec.

* change offer type in test_coinjoin

* update docs for bech32 wallets
master
Adam Gibson 5 years ago
parent
commit
3c96d412e1
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 8
      README.md
  2. 9
      docs/INSTALL.md
  3. 1
      docs/JOINMARKET-QT-GUIDE.md
  4. 149
      docs/PAYJOIN.md
  5. 196
      docs/SEGWIT-UPGRADE.md
  6. 139
      docs/USAGE.md
  7. 8
      docs/YIELDGENERATOR.md
  8. 4
      docs/tumblerguide.md
  9. 14
      docs/wallet-upgrade.md
  10. 13
      jmclient/jmclient/taker.py
  11. 2
      jmclient/jmclient/wallet.py
  12. 25
      jmclient/jmclient/yieldgenerator.py
  13. 6
      jmclient/test/test_coinjoin.py
  14. 16
      scripts/yg-privacyenhanced.py
  15. 13
      scripts/yield-generator-basic.py

8
README.md

@ -12,16 +12,16 @@ For a quick introduction to Joinmarket you can watch [this demonstration](https:
### Wallet features
* Segwit addresses in the backward compatible form (start with `3`)
* Segwit addresses (native bech32 ('bc1') by default; p2sh wrapped ('3') optionally).
* Multiple "mixdepths" or pockets (by default 5) for better coin isolation
* Ability to spend directly, or with coinjoin; export private keys; BIP49 compatible seed (Trezor, Samourai etc.) and mnemonic extension option
* Ability to spend directly, or with coinjoin; export private keys; BIP84/49 compatible seed (Trezor, Samourai etc.) and mnemonic extension option
* Fine-grained control over bitcoin transaction fees
* Basic coin control - can freeze individual utxos to stop them being spent in any transaction
* Can run sequence of coinjoins in automated form, either auto-generated (see `tumbler.py`) or self-generated sequence.
* Can specify exact amount of coinjoin (figures from 0.01 to 30.0 btc and higher are practical), can choose time and number of counterparties
* Can run passively to receive small payouts for taking part in coinjoins (see "Maker" and "yield-generator" in docs)
* GUI to support Taker role, including tumbler/automated coinjoin sequence.
* PayJoin - both [BIP78](https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki) to pay users of other wallets (e.g. merchants), as well as between two JM wallet users. This is a way to boost fungibility/privacy while paying.
* PayJoin - [BIP78](https://github.com/bitcoin/bips/blob/master/bip-0078.mediawiki) to pay users of other wallets (e.g. merchants), as well as between two compatible wallet users (Joinmarket, Wasabi, others). This is a way to boost fungibility/privacy while paying.
* Protection from [forced address reuse](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse) attacks.
### Quickstart - RECOMMENDED INSTALLATION METHOD (Linux and macOS only)
@ -62,7 +62,7 @@ If you are new, follow and read the links in the [usage guide](docs/USAGE.md).
If you are running Joinmarket-Qt, you can instead use the [walkthrough](docs/JOINMARKET-QT-GUIDE.md) to start.
If you used the old version of Joinmarket, the notes in the [scripts readme](scripts/README.md) help to understand what has and hasn't changed about the scripts.
If you used the old version of Joinmarket, the notes in the [scripts readme](scripts/README.md) help to understand what has and hasn't changed about the scripts (warning: this refers to changes from several years ago, so may be slightly outdated).
If you are looking for the available makers, run the [orderbook](docs/orderbook.md).

9
docs/INSTALL.md

@ -8,14 +8,10 @@
(You can ignore this whole section if starting from scratch).
#### Upgrading to new segwit version (0.3.0+ of this repo)
See [here](SEGWIT-UPGRADE.md).
#### Notes on upgrading versions generally:
If you just want the latest version in a new directory, go to the [releases](https://github.com/AdamISZ/joinmarket-clientserver/releases) page.
Binary executables are not currently being built; that may change in the future.
Binary executables (of JoinmarketQt) are currently being built only for Windows, please verify the signature on the .exe file attached to the release.
Otherwise: if you are upgrading from an older version, just update using git: `git pull origin master`,
or `git fetch; git checkout tags/<tagname>` for a specific tagged release, then rerun the installation
@ -134,6 +130,9 @@ There are currently two choices for installing on Windows; one, directly install
#### Installation directly on Windows
As per the note above, binaries for JoinmarketQt are being offered with releases as of 0.7.0+.
This section is for doing a full command line install, on Windows.
First, if you have not done so, install [Python](https://www.python.org/downloads/windows/) - specifically, the latest Python 3 version. Make sure to choose to install `pip` during the installation (it should be included automatically, but you can choose the custom installation option to choose it).
Be sure to choose the option that allows `python` to be in your PATH variable (you are prompted to do this at the end of the install).

1
docs/JOINMARKET-QT-GUIDE.md

@ -24,6 +24,7 @@ The github commits to the main repo, above, are signed.
* [Exporting private keys](#export-private-keys)
(*Before starting, note that the screenshots here use testnet p2sh addresses (start with '2'), but by default Joinmarket mainnet addresses are native segwit ('bc1')*).
### Walkthrough

149
docs/PAYJOIN.md

@ -16,13 +16,13 @@ For that, see [this](https://joinmarket.me/blog/blog/payjoin/) post.
4. [Doing a PayJoin payment](#doing)
a. [Using BIP78 payjoins to pay a merchant](#bip78)
a. [Using BIP78 payjoins to pay a merchant or other user's wallet](#bip78)
b. [Using Joinmarket-wallet-to-Joinmarket-wallet payjoins](#jmtojm)
c. [About fees](#fees)
5. [What if I wanted bech32 native segwit addresses?](#native)
5. [What if I wanted p2sh segwit addresses?](#p2sh)
6. [Receiving a BIP78 Payjoin payment](#receiving)
@ -117,10 +117,10 @@ So now we know that, let's continue doing the `generate` command to make a new w
Continue/complete the wallet generation with the above (`generate`) method.
(But wait again! Before you finish: want a bech32 wallet? you probably don't,
but read [this](#what-if-i-wanted-bech32-native-segwit-addresses) if you do.)
(But wait again! Before you finish: want a p2sh segwit wallet? you probably don't,
but read [this](#what-if-i-wanted-p2sh-segwit-addresses) if you do.)
The wallet you create is (if not bech32) BIP49 by default, using BIP39 12 word seed,
The wallet you create is (if not p2sh) BIP84 by default, using BIP39 12 word seed,
mnemonic extension optional (simplest to leave it out if you're not sure).
Once the `generate` method run has completed, successfully, you need to look at the wallet contents. Use
@ -132,8 +132,7 @@ python wallet-tool.py wallet-name-you-chose.dat [display]
("display" is optional because default; use `python wallet-tool.py -h` to see all possible methods).
Below is [an example](#sample) of what the wallet looks like (although
yours will be mainnet, so the addresses will start with '3' not '2').
Below is [an example](#sample) of what the wallet looks like.
Joinmarket by default uses *5* accounts, not only 1 as some other wallets (e.g. Electrum), this is to help
with coin isolation. Try to move coins from one account to another *only* via coinjoins; or, you can just
@ -143,7 +142,7 @@ that if you don't bother to do anything special, the coins in those two mixdepth
**Fund** the wallet by choosing one or more addresses in the *external* section of the first account (called
"Mixdepth 0" here). When you fund, fund to the external addresses. The internals will be used for change.
(The new standard (BIP49) *should* be compatible with TREZOR, Ledger, Electrum, Samourai and some others,
(The new standard (BIP84) *should* be compatible with TREZOR, Ledger, Electrum, Samourai and some others,
including the 12 word seed, although consider privacy concerns when sending addresses to remote servers!).
<a name="doing" />
@ -165,9 +164,9 @@ The process here is to use the syntax of sendpayment.py:
Notes on this:
* Payjoins BIP78 style are done using the `sendpayment` script, or by entering the BIP21 URI into the "Recipient" field in JoinmarketQt.
* They are done using BIP21 URIs. These can be copy/pasted from a website (e.g. a btcpayserver invoice page), note that double quotes are required (on the command line) because the string contains special characters. Note also that you must see `pj=` in the URI, otherwise payjoin is not supported by that server.
* If the url in `pj=` is `****.onion` it means you must be using Tor, remember to have Tor running on your system and change the configuration (see below) for sock5 port if necessary. If you are running the Tor browser the port is 9150 instead of 9050.
* If the url in `pj=` is `****.onion` it means you must be using Tor, remember to have Tor running on your system and change the configuration (see below) for socks5 port if necessary. If you are running the Tor browser the port is 9150 instead of 9050.
* Don't forget to specify the mixdepth you are spending from with `-m 0`. The payment amount is of course in the URI, along with the address.
* Pay attention to address type; this point is complicated, but: some servers will not be able to match the address type of the sender, and so won't be able to construct sensible Payjoin transactions. In that case they may fallback to the non-Payjoin payment (which is not a disaster). If you want to do a Payjoin with a server that only supports bech32, you will have to create a new Joinmarket wallet, specifying `native=true` in the `POLICY` section of `joinmarket.cfg` before you generate the wallet.
* Pay attention to address type; this point is complicated, but: some servers will not be able to match the address type of the sender, and so won't be able to construct sensible Payjoin transactions. In that case they may fallback to the non-Payjoin payment (which is not a disaster). If you want to do a Payjoin with a server that only supports p2sh, not bech32, you will have to create a new Joinmarket wallet, specifying `native=false` in the `POLICY` section of `joinmarket.cfg` before you generate the wallet.
Before you do such coinjoins, you may want to:
* regenerate `joinmarket.cfg`. First, rename your current `joinmarket.cfg` (in `~/.joinmarket` on Linux), then run a script once to have it regenerated from defaults. Then reapply your custom changes.
@ -203,6 +202,11 @@ max_additional_fee_contribution = default
# transaction; note it is decimal, not integer.
min_fee_rate = 1.1
# for payjoin onion service creation, the tor control configuration:
tor_control_host = localhost
# or, to use a UNIX socket
# control_host = unix:/var/run/tor/control
tor_control_port = 9051
# for payjoins to hidden service endpoints, the socks5 configuration:
onion_socks5_host = localhost
@ -244,31 +248,29 @@ BIP78 itself has various controls around fees - essentially it tries to let the
As a spender in the BIP78 protocol, you will usually see the following: a small reduction in the size of your change output as a result of the extra 1 input. Unless the payment is very small, this probably won't be significant.
<a name="native" />
<a name="p2sh" />
#### What if I wanted bech32 native segwit addresses?
#### What if I wanted p2sh segwit addresses?
You can do this, but bear in mind: PayJoin only gives its full effect if you and your receiver are using the same kind of addresses; so do this only if you and your receiver(s)/sender(s) agree on it - most BIP78 receivers at least for now will only engage in the protocol if they can provide inputs of the same type as yours.
As was noted in the BIP78 section, it may be therefore that you *need* to do this (albeit that the worst that can happen is a fallback to non-payjoin payment, which isn't a disaster).
Also note: you *cannot* do Joinmarket coinjoins if you choose a bech32 wallet (this may change in future, see [this PR](https://github.com/JoinMarket-Org/joinmarket-clientserver/pull/656)).
In the configuration file `joinmarket.cfg` (which was created in the preparatory step above), go to the
POLICY section and set:
```
[POLICY]
native = true
native = false
```
Note that this must be done *before* generating the wallet, as
the wallet internally, of course, stores which type of addresses it manages, and it can only be of two
types currently (ignoring legacy upgrades): bech32 or p2sh-segwit (starting with '3'), the latter being
the default (and the one used in Joinmarket itself).
types currently (ignoring legacy upgrades): bech32 or p2sh-segwit (starting with '3'), the former being
the default in Joinmarket as of 0.8.0+.
Note that the bech32 style wallet is written to conform to [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki),
analogous to the BIP49 case for p2sh.
Note that the p2sh-wrapped-segwit style wallet is written to conform to [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0040.mediawiki),
analogous to the BIP84 case for native/bech32.
<a name="receiving" />
@ -296,7 +298,7 @@ bitcoin:bc1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?amount=0.32000000&pj=http://p53l
Keep this process running until the payment is received.
```
... which should be self explanatory. The sender may be using Joinmarket, or a different wallet that supports Payjoin, like Wasabi. As previously noted, Payjoins will not work if the address type in use by the two wallets is different, so for Wasabi it would be necessary to use a bech32 Joinmarket wallet (as was discussed [here](#native)).
... which should be self explanatory. The sender may be using Joinmarket, or a different wallet that supports Payjoin, like Wasabi. As previously noted, Payjoins will not work if the address type in use by the two wallets is different, so for Wasabi it would be necessary to use a bech32 Joinmarket wallet (the default).
When the payment goes through you will see a chunk of logging text (most of which is serialized PSBTs being exchanged). If Payjoin was effected as intended, you will see:
@ -383,73 +385,70 @@ https://video.autizmo.xyz/videos/watch/7081ae10-dce0-491e-9717-389ccc3aad0d
<a name="sample" />
#### Sample testnet wallet display output
#### Sample wallet display output
```
JM wallet
mixdepth 0 tpubDC4qk8DsyiFYY85uktoKaiR1srWLSNRxZ2A4MXYg5LHy9XHKSTcF2tNtFpGz4LzXPcDH1kNkiww7MwipNqNSps6HSyjPTqTB18J7C4jrFMi
external addresses m/49'/1'/0'/0 tpubDFFCJfi4y6xPKquA6H6aP5EBZPupb6A9tJz8sErW8GN6D7D3s9MABPt1BczpQ3n8rBv7VLSVpu3ddvb7xEKMfNX2sMZ7XxiBD4J6kpfF7Ag
m/49'/1'/0'/0/0 2NBT6npWKxBEG8fkDjSFLDZJ7fNda4kYnAx 2.00000000 deposit
m/49'/1'/0'/0/1 2Mt7dBFikYwCQTDU129VTF9ahKWxeJjEUuF 0.00000000 new
m/49'/1'/0'/0/2 2N94bte8xWojSaX6yq2th3R3mUhvKzZqDJ9 0.00000000 new
m/49'/1'/0'/0/3 2MvSBTkCKwPHLdNPRXbovPXUM8oAfjUFPYc 0.00000000 new
m/49'/1'/0'/0/4 2MzVn3Nc3RRyN7shiVajA225xCTcaGn1PRw 0.00000000 new
m/49'/1'/0'/0/5 2MxJwv2dmkMupDuBLsEMa4HgG6GAieWHiXr 0.00000000 new
m/49'/1'/0'/0/6 2MwhdkeAcnCkam1LdVBQJ7un8syyoYB1HVH 0.00000000 new
Balance: 2.00000000
internal addresses m/49'/1'/0'/1
mixdepth 0 xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx
external addresses m/84'/0'/0'/0 xpub6FFUn4AxdqFbnTH2fyPrkLreEkStNnMFb6R1PyAykZ4fzN3LzvkRB4VF8zWrks4WhJroMYeFbCcfeooEVM6n2YRy1EAYUvUxZe6JET6XYaW
m/84'/0'/0'/0/0 bc1qt493axn3wl4gzjxvfg03vkacre0m6f2gzfhv5t 0.00000000 new
m/84'/0'/0'/0/1 bc1q2av9emer8k2j567yzv6ey6muqkuew4nh4rl85q 0.00000000 new
m/84'/0'/0'/0/2 bc1qggpg0q7cn4mpe98t29wte2rfn2rzjtn3zdmqye 0.00000000 new
m/84'/0'/0'/0/3 bc1qnnkqz8vcdjan7ztcpr68tyec7dw2yk8gjnr9ze 0.00000000 new
m/84'/0'/0'/0/4 bc1qud5s2ln88ktg83hkr6gv9s576zvt249qn2lepx 0.00000000 new
m/84'/0'/0'/0/5 bc1qw0lhq7xlhj7ww2jdaknv23vcyhnz6qxg23uthy 0.00000000 new
Balance: 0.00000000
internal addresses m/84'/0'/0'/1
Balance: 0.00000000
Balance for mixdepth 0: 2.00000000
mixdepth 1 tpubDC4qk8DsyiFYba4t8cSpadjoLYUdPwV5dAtBpzpPzgaDKPfSP42xNJq48QUKEVGHQRfFej6DCUjQqCKD8TtcqN932f27jmyjXaxVMpksos4
external addresses m/49'/1'/1'/0 tpubDEnijtftQiJpVgezdRNyKVVWGr9xKV9RgPQWHYDHpQ5utdHF7Sqh7xMUyNHcpdeKcKdQ753hFbyccRZNEHTUkHLnDaVqoXRo9XkATPtHhCp
m/49'/1'/1'/0/0 2NEsN45waxdkqjP5EnsP3K8YjMeZJh2RLx6 2.00000000 deposit
m/49'/1'/1'/0/1 2Mzhewfg6fr5jR122txdTShmLi7rH9ZscTm 2.00000000 deposit
m/49'/1'/1'/0/2 2N1vn44cv5m6PhRJMbZ1mR8dAJgHybnsT5u 2.00000000 deposit
m/49'/1'/1'/0/3 2NFwBsHkQ8mxCJWRJhkxAY28Tj8YuUJio4t 0.00000000 new
m/49'/1'/1'/0/4 2NA1YAa2VqHMSH9b2GYGBA8waUMxZTZwW5Z 0.00000000 new
m/49'/1'/1'/0/5 2MvLLp4cnP8ZVuWWDZzRCLFM2YcTfo9ALec 0.00000000 new
m/49'/1'/1'/0/6 2Mux3ZUHGmaMBiMsPDbQS56gRGGN26jMGzd 0.00000000 new
m/49'/1'/1'/0/7 2N3MWFiSHyRY3QLZgb63Vfcp4BGSFs6Y3bV 0.00000000 new
m/49'/1'/1'/0/8 2N3z5zKJPTfPc41esRRvMvjdKaSv6D6jqvY 0.00000000 new
Balance: 6.00000000
internal addresses m/49'/1'/1'/1
Balance for mixdepth 0: 0.00000000
mixdepth 1 xpub6CMAJ67vZWVXyTJEaZndxZy9ACUufsmNuJwp9k5dHHKa22zQdsgALxXvMRFSwtvB8BRJzsd8h17pKqoAyHtkBrAoSqC9AUcXB1cPrSYATsZ
external addresses m/84'/0'/1'/0 xpub6FNSLcHuGnoUbaiKgwXuKpfcbR63ybrjaqHCudrma13NDqMfKgBtZRiPZaHjSbCY3P3cgEEcdzZCwrLKXeT5jeuk8erdSmBuRgJJzfNnVjj
m/84'/0'/1'/0/0 bc1qhrvm7kd9hxv3vxs8mw2arcrsl9w37a7d6ccwe4 0.00000000 new
m/84'/0'/1'/0/1 bc1q0sccdfrsnjtgfytul5zulst46wxgahtcf44tcw 0.00000000 new
m/84'/0'/1'/0/2 bc1qst6p8hr8yg280zcpvvkxahv42ecvdzq63t75su 0.00000000 new
m/84'/0'/1'/0/3 bc1q0gkarwg8y3nc2mcusuaw9zsn3gvzwe8mp3ac9h 0.00000000 new
m/84'/0'/1'/0/4 bc1qkf5wlcla2qlg5g5sym9gk6q4l4k5c98vvyj33u 0.00000000 new
m/84'/0'/1'/0/5 bc1qz6zptlh3cqty2tqyspjk6ksqelnvrrrvmyqa5v 0.00000000 new
Balance: 0.00000000
Balance for mixdepth 1: 6.00000000
mixdepth 2 tpubDC4qk8DsyiFYdQBNNzo3vHq63Gag4eUJT29UaTVNHM89hJk6CshZ9WGemQNDh2LGDXCud8anAQ4UR7n7tSWiJtviR8WJuTB78ZbEHpFNcLH
external addresses m/49'/1'/2'/0 tpubDEY4sVvs1TX82DftUUB51Agg4Ln7BksoRGESNWtrWTDntV2fCs5wNrqiPENcXBAEHtnaY9ZaK48PRFEw1GLhcTxdDNHUyuqDd2YyNYKoVAo
m/49'/1'/2'/0/0 2NBSnSB3nVN4TA7EcNkhcRsmrdyXSQepDFE 0.00000000 new
m/49'/1'/2'/0/1 2NFtrtpdvmCRXMy1fV8w1eLWpF8MC3nre7n 0.00000000 new
m/49'/1'/2'/0/2 2NFHJvGLWU7KuNkbo8rzPwfGtCS5RtNDw7c 0.00000000 new
m/49'/1'/2'/0/3 2NGJcmeScFnTSzZzSRNHiLL8zjYeA9ngx5A 0.00000000 new
m/49'/1'/2'/0/4 2NBUAxKrNQtp49xYYHh9f6YHfo2FvYBP1NL 0.00000000 new
m/49'/1'/2'/0/5 2MyQfzKyPTfYT4vTe2d3fyGvQMoGX6GAhcr 0.00000000 new
internal addresses m/84'/0'/1'/1
Balance: 0.00000000
internal addresses m/49'/1'/2'/1
Balance for mixdepth 1: 0.00000000
mixdepth 2 xpub6CMAJ67vZWVY2cq5fmVxXw92fcgTchphGNFxweSiupYH1xYfjBiK6dj5wEEVAQeA4JcGDQGm2xcuz2UsMnDkzVmi2ESZ3xey63mQMY4x2w2
external addresses m/84'/0'/2'/0 xpub6DqkbMG3tj2oixGYniEQTFamLCHTZx9CeAbUdBttiGuYwgfGZbrLMor8LWeJBUqTpsa81JcJqAUXuDxhXdLpKDxJAEqKMqPgJyXstj5dp3o
m/84'/0'/2'/0/0 bc1qwtdgg928wma8jz32upkje7e4cegtef7yrv233l 0.00000000 new
m/84'/0'/2'/0/1 bc1qhkuk2gny4gumrxcaw999uq3jm3fjrjvcwz7lz3 0.00000000 new
m/84'/0'/2'/0/2 bc1qvu753lkltc8akfasclnq89tdv8yylu2alyg76y 0.00000000 new
m/84'/0'/2'/0/3 bc1qal3r040k26cw2f08337huzcf00hrnws5rhfrz3 0.00000000 new
m/84'/0'/2'/0/4 bc1qpv4nm7wwtxesgwsr0g0slxls33u0w02gqx2euk 0.00000000 new
m/84'/0'/2'/0/5 bc1qk3ekjzlvw3uythw738z7nvwe2sg93w2rtuy6ml 0.00000000 new
Balance: 0.00000000
internal addresses m/84'/0'/2'/1
Balance: 0.00000000
Balance for mixdepth 2: 0.00000000
mixdepth 3 tpubDC4qk8DsyiFYgXoNb3UmiaG2veSTdrLCxEBUsTEQnDgQLCaC8Yg1z1Bcwn4ZQivNhgBxHEWH7j8hbRx7rab2kYLy4r4PXxor4Ho3A5AJvVH
external addresses m/49'/1'/3'/0 tpubDEnwog2atqaSLe9xVTTdqxY5ynysqeQPsXuaKrZ6HaYCJcFPY7LmhepmwFTJYTkqf1w5jgLQmoZvREyk9qiq4P2A2fSGTyj62WUE4VjXK76
m/49'/1'/3'/0/0 2MtckYQLD6bJZiPXffW7m5rryMao7u4ktng 0.00000000 new
m/49'/1'/3'/0/1 2N9KrH5Bi35ZH3DVUwD67eh8MtQD1LLhgCa 0.00000000 new
m/49'/1'/3'/0/2 2N6zLabMeXTXfyzQttr6PBV2JdbZPrVd9i8 0.00000000 new
m/49'/1'/3'/0/3 2MzYTWMjXcv4NBce5PKcDAceT7gMuYrGovc 0.00000000 new
m/49'/1'/3'/0/4 2N6tYykyCZLtvP1RJZvgZ9a7c6xbQaqpE66 0.00000000 new
m/49'/1'/3'/0/5 2N2o3eJ9h2BC5q3TzPVqhn9gmgWBjaL67Hu 0.00000000 new
mixdepth 3 xpub6CMAJ67vZWVY3uty61M6jeGheGU5ni5mQmqMW2QLQbEa8ZQXuBw1K2umKFZsmU8EMEafJZKQkGS1trtWE5dtz4XmDbvLvUccAPn26ZC5i2o
external addresses m/84'/0'/3'/0 xpub6EvT4QFPRdkt2sji3QdLLZjkJQmk7G2y3umT99ceomKTXGYvZ5S9TLaGos6cEugXEuxS6s9kvSUj1Xvpiu65dn5yzK7CgdZLzXawpKC9Mpe
m/84'/0'/3'/0/0 bc1q9ph5l2gknjezcmzv84rnhu4df566jgputzef7l 0.00000000 new
m/84'/0'/3'/0/1 bc1qrlvmmxfuryr3mfhssjv45h0fl6s43g3vzrkwca 0.00000000 new
m/84'/0'/3'/0/2 bc1q40xkajgv9q42ve92zstwjc9v4jgauxme9su6uc 0.00000000 new
m/84'/0'/3'/0/3 bc1q38pfk8yfnu97v4mckkuk2dhk9u8geuyzu9c0hc 0.00000000 new
m/84'/0'/3'/0/4 bc1q2qzxyw56em9qdxc5z5s5xjz3j6s2qlzn3juvtu 0.00000000 new
m/84'/0'/3'/0/5 bc1qd2f8f3dau5pfjqu7dpuvt6fahj36w4rgl3xevr 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/1'/3'/1
internal addresses m/84'/0'/3'/1
Balance: 0.00000000
Balance for mixdepth 3: 0.00000000
mixdepth 4 tpubDC4qk8DsyiFYj7GF4LV97c9f7Yff1mrwnxkpi5twGSLmesmPyM4xXBWsxMw9ZLFycVVC4TeeX1ESjNP4rVVrJEDVCm7C3UMvZH9vs6srsAi
external addresses m/49'/1'/4'/0 tpubDFA3XKgf2ZiusZHr4we5utkrQ9toN5s7QGKndNMrdQFQfjQU6yiiMT65tmXFCPduSc7muLFegAi36pv4LCdRnhpRYp2QUpm1izyrboWSjzV
m/49'/1'/4'/0/0 2N18HGRJyaaUwLQFTyfjqZoXGCV8Yv5rbwD 0.00000000 new
m/49'/1'/4'/0/1 2Mt94Y4iguYLkBAhsXT5a1P8VMTQ4kxdZJD 0.00000000 new
m/49'/1'/4'/0/2 2N5vYyG1gx8ht2JCKkuVqow3Qn51cHrwaxh 0.00000000 new
m/49'/1'/4'/0/3 2N44ZtKYu21p1qN4DBoTCYZL2sms6YBeWVW 0.00000000 new
m/49'/1'/4'/0/4 2NF9p2b2PfHvXiPmPP5JPq4CRxKn47LPZrW 0.00000000 new
m/49'/1'/4'/0/5 2MwgfAvbPc4ASD84WdBYo2FM5bXBVG1rRG9 0.00000000 new
mixdepth 4 xpub6CMAJ67vZWVY7gT4oJQBMc1fhbausT57yNVLCLCMwaGed5spHKaQY1EMQxvL2vTgDfhEimuAy7bzBE1qx5uY6D7cpUjQtXPHpyJzFuUtQPN
external addresses m/84'/0'/4'/0 xpub6EQWpKsBTG3N9TFU4v6WtCcBJuLAeTZTcUwVJTxYUAsHeVPFdey4qT1dg4G7MqvnFFgHZDxqTo37S81UWUA2BqKKoTff1pcHTcSFzxyp5JG
m/84'/0'/4'/0/0 bc1qdpjh3ewm367jm5eazqdf8wfrm09py50wn47urs 0.00000000 new
m/84'/0'/4'/0/1 bc1q2x0fmtms5nr3wz3x3660c8wampg7t22e6m30t8 0.00000000 new
m/84'/0'/4'/0/2 bc1q23595yg3dkj8gd3jrgup0hyzslhzf9skrg50r5 0.00000000 new
m/84'/0'/4'/0/3 bc1qw48asjpkwm3k2w8cketqhrre0uwq9f7ypwzmxl 0.00000000 new
m/84'/0'/4'/0/4 bc1qf3wljw44utyv7qd0z57zvdkfl20y470mva0nes 0.00000000 new
m/84'/0'/4'/0/5 bc1qz3f80rtv0ux85d7rc06ldtvmpqyfx6ly48c9pa 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/1'/4'/1
internal addresses m/84'/0'/4'/1
Balance: 0.00000000
Balance for mixdepth 4: 0.00000000
Total balance: 8.00000000
Total balance: 0.00000000
```

196
docs/SEGWIT-UPGRADE.md

@ -1,196 +0,0 @@
### What if I don't want to migrate to segwit yet?
If, for whatever reason, you want to keep using the non-segwit version of Joinmarket,
you can do so by adding the following entry in your `joinmarket.cfg` file:
```
[POLICY]
segwit = false
```
(obviously, add it *into* the `POLICY` section, don't create a duplicate of that
section. Also make sure to enter exactly `false` in lower case, otherwise it
will be ignored. The default is segwit).
If you do this, the pre-existing Joinmarket wallet should load fine and you should
be able to do coinjoins just as before.
Note, however, that most are migrating to segwit, and we strongly encourage it
(it's better not to have a split into two groups), not least because segwit
transactions are cheaper.
The rest of this document will assume you *do* want to migrate.
---
### Migrating to a new segwit based wallet.
To do joinmarket coinjoins with other participants using segwit, you need to use
a wallet with segwit addresses. These addresses are P2SH (start with '3' on mainnet);
note they are *not* multisig, however, they are yours only (technically we are using
address type P2SH/P2WPKH).
(Some parts of this are a repeat of what's in the [usage guide](USAGE.md)).
#### If you don't have an existing Joinmarket wallet:
You can go into the `scripts/` directory, which contains the `wallet-tool.py` script,
and follow the instructions as in the first half of:
https://github.com/JoinMarket-Org/joinmarket/wiki/Using-the-JoinMarket-internal-wallet
You will notice the main difference from what's shown there is that after using
the `generate` command, your new wallet has addresses starting with '3' not '1'.
Also, the BIP32 paths are different, see the bottom of this page for some details on that.
#### If you do have an existing Joinmarket wallet:
Migrating coins to this new-style wallet can be done in these steps:
* Install this new version (0.3.0+), use "Quickstart" from the [readme](../README.md) or see [here](INSTALL.md)
* Generate a new wallet; go into the `scripts/` directory and do the same as before:
python wallet-tool.py generate
Once you've written down the 12 word seed and saved the new .json file, check the
addresses with:
python wallet-tool.py newwallet.json
(or whatever you called the file). You should see a set of '3' addresses (or '2' on testnet) instead of '1'. Also the
spacing/layout may look a bit different, but it's the same information.
Note down at least 3 addresses from mixdepth 0 if you plan to use as a Taker; if as
a Maker (yieldgenerator), best to note down one address from each mixdepth.
Next, load your old wallet; you have two options - either (1) use your old Joinmarket
installation, or (2) use this one, and go into joinmarket.cfg and add:
segwit = false
to the `[POLICY]` section. This will allow you to run `python wallet-tool.py` and it
will find the old wallet. Whether using method (1) or (2), the next step is the same:
Use `python sendpayment.py -N 0 -m [mixdepth] oldwalletname 0 destaddr` to send coins from
your old wallet, mixdepth 0, into the new one you've created, with a sweep from that
mixdepth. The -N 0 means using direct-send, i.e. not using joinmarket/IRC.
Don't forget to reset `tx_fees` in your joinmarket.cfg
if you want to adjust the projected fee.
If you've used (2), then delete the line `segwit = false` from joinmarket.cfg, and
reload the new wallet with `python wallet-tool.py newwalletname.json`
Once you're sure it's working you can repeat this process for any number of mixdepths
for which you want to transfer coins.
#### Typical wallet output (testnet) for reference
```
JM wallet
mixdepth 0 tpubDC3ynQKo14bet1kCgg5ms7d5ABHVkrWLKLqbMQTiDY5T3nd4dUCCLNzJFyj78FvcQbDsJCk96AJfdATnS7Cf1VaM2JsqM73i2VyBeoQVSwa
external addresses m/49'/1'/0'/0 tpubDEdFHGLtyru2nSRdv4F3GXw8MQBx5mVaJQeTP7Am6okGeQLfqt9ysD2npE9eFQXNBfcamxooyJ4nKfb2rQzG97zNsG9tex4YRUKRwRMBvR5
m/49'/1'/0'/0/000 2NGQED4c5BZL1RNVgzJHM7BAThPyT1GXXdf 2.00000000 used
m/49'/1'/0'/0/001 2N2xYemrtcTHdVxejvAKgYcbx27pJbWcC7D 0.00000000 new
m/49'/1'/0'/0/002 2N6D25kEWEgN78rG8i8soBo2N4kJ3U6jKhK 0.00000000 new
m/49'/1'/0'/0/003 2Mzerss9QDXi3PyyxiTwSN2xV3977EBmRK9 0.00000000 new
m/49'/1'/0'/0/004 2MtFEA9H43ptf2MUcZoA9WFQvg6XF5iVgsk 0.00000000 new
m/49'/1'/0'/0/005 2MzJTsaZFBc3HDktYKvd8rkTGeDMCmaMWPn 0.00000000 new
m/49'/1'/0'/0/006 2Mu2NezBjuzXKaJKrPAh7a9TcWa7REDXNXt 0.00000000 new
Balance: 2.00000000
internal addresses m/49'/1'/0'/1
Balance: 0.00000000
Balance for mixdepth 0: 2.00000000
mixdepth 1 tpubDC3ynQKo14bevgk8tW8uX6TbdThjGcLkULcZUtMkeH7QVK5wXXF9nLF8dYUrvVkVcbUpsSgCZyQDajHNJzcg8f6FDHSFgS4ask5BgdeTock
external addresses m/49'/1'/1'/0 tpubDFRo71SzBY98U2suh1CVgFV8s7SbdTUYj3xgg4Zk9XrPAFfXg7krxCLsVmq8pYW7bWcnRMPrRP9uVrgLSztKGvHJE2Re64CgNPNddpqzArm
m/49'/1'/1'/0/000 2N42BUaNAGuEsVxXtgR2i2XRWwFyrcku7xJ 2.00000000 used
m/49'/1'/1'/0/001 2N6wivgfa9SNAmLkNLTA5tjLa6RbteiJ9NP 2.00000000 used
m/49'/1'/1'/0/002 2N8fsY6cPigbkyAUPoYuqXrvwSTNbDuSs38 2.00000000 used
m/49'/1'/1'/0/003 2N7p1vw9yB5GRyX2rDMfUGu6szVtNFrsJ4J 0.00000000 new
m/49'/1'/1'/0/004 2N8ezrbwLe4HVRKupxGDxqqah6QWvpafCMr 0.00000000 new
m/49'/1'/1'/0/005 2MshrDThyZD6irvPzqjPm7UENwptL9jwWMu 0.00000000 new
m/49'/1'/1'/0/006 2Mw8zcteMmzdEqtVDjWrJ425wSog3TsSzgt 0.00000000 new
m/49'/1'/1'/0/007 2MukpuXRWAa1oSZnvcodybvnEz9L2EF9bLv 0.00000000 new
m/49'/1'/1'/0/008 2N6Zhsg7E6KjEY3PUaLsZqpzpfLrqiTkUaE 0.00000000 new
Balance: 6.00000000
internal addresses m/49'/1'/1'/1
Balance: 0.00000000
Balance for mixdepth 1: 6.00000000
mixdepth 2 tpubDC3ynQKo14bf1LnhHPQQ2ReJCZzV24AViKCKGW99SBwFr3DLSio24mwjNcHZwDqdGUejr6K3WEhv7DdASLNrFsZhx8rgbjzTtYGjeuZLPtf
external addresses m/49'/1'/2'/0 tpubDEunZR6GYohjUiAsNecPvm6zA63apCuKe4J8bJz9tjJAuNy485e4LQFAmuF3YVzHFbUvbDpGz1SvGx1tLvoYrExo5Cmhbnw9N4RcJfQVcy8
m/49'/1'/2'/0/000 2MujbkR3UsUfYf53e4TNErWqpxLEFeX7CjF 0.00000000 new
m/49'/1'/2'/0/001 2N6c1979MmfdZPhGQHpPx4upZoh9A66tpXx 0.00000000 new
m/49'/1'/2'/0/002 2N12iWBShn3NhbqiJVrERJ1ArE2aNbJLiuC 0.00000000 new
m/49'/1'/2'/0/003 2N2WRcxDYkaNHxnv4upAiqCCVRz9YyMqvCA 0.00000000 new
m/49'/1'/2'/0/004 2ND2k7Bsh21dNqC52dK5GtXeXhfQDUfpuc6 0.00000000 new
m/49'/1'/2'/0/005 2N9PvkbGu93vE52v433maZwjkjMQvcXgguc 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/1'/2'/1
Balance: 0.00000000
Balance for mixdepth 2: 0.00000000
mixdepth 3 tpubDC3ynQKo14bf3T8XrYA9CgKLmpr1wsAZf2VuGhku36bXQMaCRYges3NWd9AW7GoFTiCAwyPWTTz4V99A3VDSKryPgG7US1vaNLB8daxFWXh
external addresses m/49'/1'/3'/0 tpubDEf2oHNW6QCmUF4moLgMpjhgmsnJgDGdfrihxBFGAXncbnvhHBAWD8EFe6hphPpBxtoEaHVaSvqTQW52QJ282vMQxvDNPDzPrnrDu8Hem6p
m/49'/1'/3'/0/000 2N5Ybuqi3a8Wfg8gZfjN5CVNBUYPirsNda6 0.00000000 new
m/49'/1'/3'/0/001 2MxQgX1Ykcj1fJzeVZDJ7xmcdRZjxnB5PHp 0.00000000 new
m/49'/1'/3'/0/002 2N7JwhZEo2CjphzU8FRVJm7CU8UF2FVRYPF 0.00000000 new
m/49'/1'/3'/0/003 2N5MJvtRGTdQSipDsBgDLHQzc3hzwMdk6BK 0.00000000 new
m/49'/1'/3'/0/004 2NGUERANYNAZamXWGMtYxJy49WvQra69FPP 0.00000000 new
m/49'/1'/3'/0/005 2MvxVh7hpxCGfojwmtW32K9QkkahP2bvSyZ 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/1'/3'/1
Balance: 0.00000000
Balance for mixdepth 3: 0.00000000
mixdepth 4 tpubDC3ynQKo14bf5z1LUdPiEFaJ3omV4y2VasyT5PUL8H9JhShXMvn24zRhRdpMA5oAVwheLmvL2J6r2NFoUdoSVhZjCWd1aUxsUfa332cnEpk
external addresses m/49'/1'/4'/0 tpubDEW6kkqjuEdqiNCpPixL2ToQWsRNojGHzWBfXpUDp9cyix8en1HY2ZwndU3KCNBbdpac5GiUwkqR2jiZjtRedAAbnNHWL86cEDMsMoFXiTH
m/49'/1'/4'/0/000 2NEraA2d5cV83qQkg7oebhx2ugGT4eF9QY5 0.00000000 new
m/49'/1'/4'/0/001 2N5RKKMTFXA8Punt6H9JrPQFnNJFz3DSe9W 0.00000000 new
m/49'/1'/4'/0/002 2NBzFW263ohqGyK53HuFcB7kSLkvBSV38gc 0.00000000 new
m/49'/1'/4'/0/003 2NCLjgm6Dgc3q4QSNiRUMKbt2aQSidGNfrX 0.00000000 new
m/49'/1'/4'/0/004 2MvQkFkhZeymz8r1XtSUT3fz3hdaZp2dxt5 0.00000000 new
m/49'/1'/4'/0/005 2N9zM5Jv4tjwJ2ezKMQi4ECjvheWugWajhj 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/1'/4'/1
Balance: 0.00000000
Balance for mixdepth 4: 0.00000000
Total balance: 8.00000000
```
### Information about the new wallet type and compatibility.
First, the seed phrase is now based on BIP39, but this is transparent: it's still
a 12 word seed, but based on a new dictionary.
It uses the [mnemonic](https://github.com/trezor/python-mnemonic) package/implementation.
Second, this new wallet type is not compatible with the old; that doesn't make sense - even if it generated the same private keys,
you would still have to transfer to new segwit style outputs.
Third, the new type is based on [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki),
which is currently supported by TREZOR, Ledger, Electrum (via custom HD path option, only one account at a time), Samourai, Eclair to my knowledge, and probably others.
So these Joinmarket wallets could be loaded into those wallets, but be wary of privacy issues if querying your addresses over some external server.
BIP49 is a modification of BIP44 for segwit, but really it's just a new BIP32 HD path.
(To get even further into the technical weeds, these standards (44/49) use hardened derivation except for keys below the account level).
### Fees
Segwit doesn't have much direct technical import for Joinmarket, since coinjoin
(at least when properly implemented) isn't subject to any dangers from transaction
malleability.
However, there can be significant, if not huge, fee savings based on the change from 'size'
to 'weight' in block limits. Instead of paying (fee/kB) * kB of tx size, you pay
for (non-witness + 0.25 * witness)/4 * (fee/kB) (very rough explanation), which rough
calculations suggests might give ~ 25-30% savings over a non-segwit tx in a typical scenario.
Somewhat higher fee savings may be achieved if we switched to a "native" segwit address in future,
rather than a P2SH-wrapped one.
#### Note for Makers
Since segwit-style joinmarket must be done "all-in-one" for privacy (otherwise a Taker
risks creating a single '1' address output), the yieldgenerator in this implementation
makes `swreloffer` and `swabsoffer` offer types, and won't also offer original-type offers.
However, the parameters of the offer are the same, and are still set in the (now much
simplified) `yield-generator-basic.py` or `yg-privacyenhanced.py` scripts.
Other variants may be added later subject to anyone getting around to doing it.

139
docs/USAGE.md

@ -174,72 +174,75 @@ Notice that here you **don't** need to rescan, because you are not "recovering a
```
JM wallet
mixdepth 0 xpub6Crt4fcfpnrNxW45MzuV626z4fjddsuFGwRn1DXdpwnDkBMR12GKdBzW8euDqLSqRRv2eZmcJy8FSQLWEosC6wFZAZEv3FJMtvZ7W1CkQDi
external addresses m/49'/0'/0'/0 xpub6FQFAscJgwd8MXCcAT8A1hgx9vigrgVoXVNTAKHj2aK3NR2Zf1CbFNXD8G8X9dspGXLY9eiEzBWaypr24owJ8r1aTKgMbUZoTnQ36bBwQB3
m/49'/0'/0'/0/0 35SrGbUt9FpfA6xqKMpNaiTNyeuXagBi7Y 0.00000000 new
m/49'/0'/0'/0/1 39hc2xfA6i9kWZdXMwH4Pd9dWUvDKocGd3 0.00000000 new
m/49'/0'/0'/0/2 371MJcjFG4cEpz8RVdYb1L8PkA9tZYySGZ 0.00000000 new
m/49'/0'/0'/0/3 39eTy635wLCyBbphUTNnSB2V9LnvgdndNo 0.00000000 new
m/49'/0'/0'/0/4 33T8eNr54maWNZYQjoZwpLA2HGk7RJaLVb 0.00000000 new
m/49'/0'/0'/0/5 35kJoTSxHtQbKUg2jvjDVqcY9iXoH2cTqD 0.00000000 new
mixdepth 0 xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx
external addresses m/84'/0'/0'/0 xpub6FFUn4AxdqFbnTH2fyPrkLreEkStNnMFb6R1PyAykZ4fzN3LzvkRB4VF8zWrks4WhJroMYeFbCcfeooEVM6n2YRy1EAYUvUxZe6JET6XYaW
m/84'/0'/0'/0/0 bc1qt493axn3wl4gzjxvfg03vkacre0m6f2gzfhv5t 0.00000000 new
m/84'/0'/0'/0/1 bc1q2av9emer8k2j567yzv6ey6muqkuew4nh4rl85q 0.00000000 new
m/84'/0'/0'/0/2 bc1qggpg0q7cn4mpe98t29wte2rfn2rzjtn3zdmqye 0.00000000 new
m/84'/0'/0'/0/3 bc1qnnkqz8vcdjan7ztcpr68tyec7dw2yk8gjnr9ze 0.00000000 new
m/84'/0'/0'/0/4 bc1qud5s2ln88ktg83hkr6gv9s576zvt249qn2lepx 0.00000000 new
m/84'/0'/0'/0/5 bc1qw0lhq7xlhj7ww2jdaknv23vcyhnz6qxg23uthy 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/0'/0'/1
internal addresses m/84'/0'/0'/1
Balance: 0.00000000
Balance for mixdepth 0: 0.00000000
mixdepth 1 xpub6Crt4fcfpnrP2GZnVuT1qi9aw9cpCuXcnGEjAKhaoWAHq5M4pWX64DNio3XHirY5uTCZCi6vTmaLjU5YQXbVsTjyEdCE2zn3S2fzBNFjxs8
external addresses m/49'/0'/1'/0 xpub6E2EnYy6yBXvE9U1nR5sSH58YiwbsKFZzaMkgMY5jrt2XFe4D5HVwikeTWyjuoczjQhJNezkwxrKAbUPMEDYHmbiaaiEAeXcL1yAcEAqtd7
m/49'/0'/1'/0/0 3DdhEr9GCoMDVRLNGAwi9rb8F4HQX8newY 0.00000000 new
m/49'/0'/1'/0/1 342XPkCQYzZkdUaB9TGPfVhf1iX55yE4gH 0.00000000 new
m/49'/0'/1'/0/2 33RaQJTn1P8KNUvNnPRFM19zHjPhzuyCqc 0.00000000 new
m/49'/0'/1'/0/3 3LydaxypMyYrbDFFp61f9rnZRcAJnZ5sv5 0.00000000 new
m/49'/0'/1'/0/4 36u2ykPy6Y9tg811B8XjYoPjpTtEg98RPd 0.00000000 new
m/49'/0'/1'/0/5 3AfSFczJEUN5RRbXirf8Pc74ve3ZaBVF8r 0.00000000 new
mixdepth 1 xpub6CMAJ67vZWVXyTJEaZndxZy9ACUufsmNuJwp9k5dHHKa22zQdsgALxXvMRFSwtvB8BRJzsd8h17pKqoAyHtkBrAoSqC9AUcXB1cPrSYATsZ
external addresses m/84'/0'/1'/0 xpub6FNSLcHuGnoUbaiKgwXuKpfcbR63ybrjaqHCudrma13NDqMfKgBtZRiPZaHjSbCY3P3cgEEcdzZCwrLKXeT5jeuk8erdSmBuRgJJzfNnVjj
m/84'/0'/1'/0/0 bc1qhrvm7kd9hxv3vxs8mw2arcrsl9w37a7d6ccwe4 0.00000000 new
m/84'/0'/1'/0/1 bc1q0sccdfrsnjtgfytul5zulst46wxgahtcf44tcw 0.00000000 new
m/84'/0'/1'/0/2 bc1qst6p8hr8yg280zcpvvkxahv42ecvdzq63t75su 0.00000000 new
m/84'/0'/1'/0/3 bc1q0gkarwg8y3nc2mcusuaw9zsn3gvzwe8mp3ac9h 0.00000000 new
m/84'/0'/1'/0/4 bc1qkf5wlcla2qlg5g5sym9gk6q4l4k5c98vvyj33u 0.00000000 new
m/84'/0'/1'/0/5 bc1qz6zptlh3cqty2tqyspjk6ksqelnvrrrvmyqa5v 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/0'/1'/1
internal addresses m/84'/0'/1'/1
Balance: 0.00000000
Balance for mixdepth 1: 0.00000000
mixdepth 2 xpub6Crt4fcfpnrP2Tjc95HKmSgaCpi9P9EM54B12XAUfdnyAyoftFpNyikSK4pBtsvqZAnj8grDFf61xDmAHYimQXvaQkoTY3h9G5BAxHuYgvn
external addresses m/49'/0'/2'/0 xpub6DrRZxJu5zEgxVMcrXmKGGeEQMgfh1MeZXvDXVYndqsqoFaJQUA94GbD1JX2p7Yw5NLcCUgg3WQXtXk5eP4vnNjGkDwA3FJoFFkE4PytauC
m/49'/0'/2'/0/0 39uPqzuW6CiyRSUvdrBYfaqSD2AtH2k4wf 0.00000000 new
m/49'/0'/2'/0/1 3FVYzJWE6g6kGj3hF7B5e7QpDQafBcUdnx 0.00000000 new
m/49'/0'/2'/0/2 3HjYatHB5tZFGcC2SUCBqT1zCM7AwgGE5r 0.00000000 new
m/49'/0'/2'/0/3 3CDco5iVa2iyEHGjXcAojsod6QDxeNedFg 0.00000000 new
m/49'/0'/2'/0/4 3LKaYFENU16ix8FngQk6m9VmQFGaATEeCu 0.00000000 new
m/49'/0'/2'/0/5 3B3TtgU6VgLF6BzQeG5znKZHpr3zgoftZC 0.00000000 new
mixdepth 2 xpub6CMAJ67vZWVY2cq5fmVxXw92fcgTchphGNFxweSiupYH1xYfjBiK6dj5wEEVAQeA4JcGDQGm2xcuz2UsMnDkzVmi2ESZ3xey63mQMY4x2w2
external addresses m/84'/0'/2'/0 xpub6DqkbMG3tj2oixGYniEQTFamLCHTZx9CeAbUdBttiGuYwgfGZbrLMor8LWeJBUqTpsa81JcJqAUXuDxhXdLpKDxJAEqKMqPgJyXstj5dp3o
m/84'/0'/2'/0/0 bc1qwtdgg928wma8jz32upkje7e4cegtef7yrv233l 0.00000000 new
m/84'/0'/2'/0/1 bc1qhkuk2gny4gumrxcaw999uq3jm3fjrjvcwz7lz3 0.00000000 new
m/84'/0'/2'/0/2 bc1qvu753lkltc8akfasclnq89tdv8yylu2alyg76y 0.00000000 new
m/84'/0'/2'/0/3 bc1qal3r040k26cw2f08337huzcf00hrnws5rhfrz3 0.00000000 new
m/84'/0'/2'/0/4 bc1qpv4nm7wwtxesgwsr0g0slxls33u0w02gqx2euk 0.00000000 new
m/84'/0'/2'/0/5 bc1qk3ekjzlvw3uythw738z7nvwe2sg93w2rtuy6ml 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/0'/2'/1
internal addresses m/84'/0'/2'/1
Balance: 0.00000000
Balance for mixdepth 2: 0.00000000
mixdepth 3 xpub6Crt4fcfpnrP5B7ysPePnY98sKaLAdu9yCbHpkodb6evSKhr4BWvpB7nQquPdzncTuhMxmUhEcVNuYpXQf9i6VN9DFYu3PgPMckuu4P7EeQ
external addresses m/49'/0'/3'/0 xpub6En2j7xGy2ihoYhpmTyDL1eER5B6rdas1HotoBiLbSXuXBMwZnjJTRefyJKVLUTfwDMgyATqZAwbZdKb8gQ8Fbno4XhUMPe6XBuN4LSsXN2
m/49'/0'/3'/0/0 3LhThkjSvYmmXLNLMcXghbvaoGgDitwfmi 0.00000000 new
m/49'/0'/3'/0/1 3LTwvukpZqsf9ghqnNQVu8szgScjoVnLdh 0.00000000 new
m/49'/0'/3'/0/2 35FRiSaZ6Yotr3YB3yX9JgqAbsxCnuTBfm 0.00000000 new
m/49'/0'/3'/0/3 3H7S5ZjYaWgSTXA1RFwGNytS2zsK1PfXoN 0.00000000 new
m/49'/0'/3'/0/4 33b8j2nPCFCWXb7wDHPRggUFoPJMwGQYYt 0.00000000 new
m/49'/0'/3'/0/5 3PE7fen989oPZn7XaRSAu3fvGN1P57SB9W 0.00000000 new
mixdepth 3 xpub6CMAJ67vZWVY3uty61M6jeGheGU5ni5mQmqMW2QLQbEa8ZQXuBw1K2umKFZsmU8EMEafJZKQkGS1trtWE5dtz4XmDbvLvUccAPn26ZC5i2o
external addresses m/84'/0'/3'/0 xpub6EvT4QFPRdkt2sji3QdLLZjkJQmk7G2y3umT99ceomKTXGYvZ5S9TLaGos6cEugXEuxS6s9kvSUj1Xvpiu65dn5yzK7CgdZLzXawpKC9Mpe
m/84'/0'/3'/0/0 bc1q9ph5l2gknjezcmzv84rnhu4df566jgputzef7l 0.00000000 new
m/84'/0'/3'/0/1 bc1qrlvmmxfuryr3mfhssjv45h0fl6s43g3vzrkwca 0.00000000 new
m/84'/0'/3'/0/2 bc1q40xkajgv9q42ve92zstwjc9v4jgauxme9su6uc 0.00000000 new
m/84'/0'/3'/0/3 bc1q38pfk8yfnu97v4mckkuk2dhk9u8geuyzu9c0hc 0.00000000 new
m/84'/0'/3'/0/4 bc1q2qzxyw56em9qdxc5z5s5xjz3j6s2qlzn3juvtu 0.00000000 new
m/84'/0'/3'/0/5 bc1qd2f8f3dau5pfjqu7dpuvt6fahj36w4rgl3xevr 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/0'/3'/1
internal addresses m/84'/0'/3'/1
Balance: 0.00000000
Balance for mixdepth 3: 0.00000000
mixdepth 4 xpub6Crt4fcfpnrP9pZBowaYjC7595HXETHFw2YnqtukLnqpfb4PWbhWwt5jPdskLo8ZZbHBnccexTJUArt4V8C7592K3LvsrYkrvsQMJFiPx8z
external addresses m/49'/0'/4'/0 xpub6E37s5W8C63FxsgcpMbH43ssUi8CQzfo3PrfSWfn9jKTYZgR4QZBCymJ8TPw3Vx5zoQ7aSgkqrEKr1NEerZuN8okV7w1JhNg2hoYEWohtT4
m/49'/0'/4'/0/0 39n1tYKnPQ47bgCmsPWDHxuk2Mxo6GE4LZ 0.00000000 new
m/49'/0'/4'/0/1 3BoLqHDSHdMHyrSEAP31bBzzw45bFwZhy7 0.00000000 new
m/49'/0'/4'/0/2 31mo7D9UDmoStafYcyHpwV9sWY7oP9jUVQ 0.00000000 new
m/49'/0'/4'/0/3 3JMVGEyZ5nyJR9NVsfNY93c34xx9rEtzmq 0.00000000 new
m/49'/0'/4'/0/4 3AdD86dw59Q5EGHVupkHzR8pM4sW45bKqX 0.00000000 new
m/49'/0'/4'/0/5 3Gu7jTxcmh5dHJXgCE7Z5fdMgUWuenE2GE 0.00000000 new
mixdepth 4 xpub6CMAJ67vZWVY7gT4oJQBMc1fhbausT57yNVLCLCMwaGed5spHKaQY1EMQxvL2vTgDfhEimuAy7bzBE1qx5uY6D7cpUjQtXPHpyJzFuUtQPN
external addresses m/84'/0'/4'/0 xpub6EQWpKsBTG3N9TFU4v6WtCcBJuLAeTZTcUwVJTxYUAsHeVPFdey4qT1dg4G7MqvnFFgHZDxqTo37S81UWUA2BqKKoTff1pcHTcSFzxyp5JG
m/84'/0'/4'/0/0 bc1qdpjh3ewm367jm5eazqdf8wfrm09py50wn47urs 0.00000000 new
m/84'/0'/4'/0/1 bc1q2x0fmtms5nr3wz3x3660c8wampg7t22e6m30t8 0.00000000 new
m/84'/0'/4'/0/2 bc1q23595yg3dkj8gd3jrgup0hyzslhzf9skrg50r5 0.00000000 new
m/84'/0'/4'/0/3 bc1qw48asjpkwm3k2w8cketqhrre0uwq9f7ypwzmxl 0.00000000 new
m/84'/0'/4'/0/4 bc1qf3wljw44utyv7qd0z57zvdkfl20y470mva0nes 0.00000000 new
m/84'/0'/4'/0/5 bc1qz3f80rtv0ux85d7rc06ldtvmpqyfx6ly48c9pa 0.00000000 new
Balance: 0.00000000
internal addresses m/49'/0'/4'/1
internal addresses m/84'/0'/4'/1
Balance: 0.00000000
Balance for mixdepth 4: 0.00000000
Total balance: 0.00000000
```
The [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) xpub keys of each external branch are shown in case that is needed.
The BIP32 derivation paths are also shown; for Joinmarket they are defined by [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki); for more on this see [below](#structure).
The BIP32 derivation paths are also shown; for Joinmarket they are defined by [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki); for more on this see [below](#structure).
If you set `native = false` in the `[POLICY]` section of your `~/.joinmarket/joinmarket.cfg` file, you will create a wallet with '3' addresses, which is p2sh wrapped segwit, instead of 'bc1' addresses; this uses BIP49 instead of BIP84, but is recoverable similarly (it is slightly more expensive in terms of tx fees; this was the default for Joinmarket pre-0.8.0).
**Bitcoins should be sent to empty external addresses** (sometimes known as receive addresses). You'll notice in
the above that while there are fields also for *internal addresses*, they are empty. That's because zero-balance internal addresses (also known as change addresses) are hidden by default. Using 'displayall' as the second argument will show all addresses in wallet, including empty used ones.
@ -292,34 +295,34 @@ The `showseed` command will display the mnemonic for an existing wallet file, in
<a name="privkeys" />
### Recovering Private Keys
It is possible to recover a Joinmarket wallet in Trezor, Electrum or a number of other wallets, because it uses BIP49. But note that this is not ideal for privacy reasons (if you contact a server with your addresses), and also that because Joinmarket uses multiple accounts (=mixdepths), it may be more difficult than expected.
It is possible to recover a Joinmarket wallet in Trezor, Electrum or a number of other wallets, because it uses BIP84. But note that this is not ideal for privacy reasons (if you contact a server with your addresses), and also that because Joinmarket uses multiple accounts (=mixdepths), it may be more difficult than expected.
In difficult recovery situations, the `-p` command line flag can be used to print out private keys. Be very careful and consider this advanced usage:
```
...
JM wallet
mixdepth 0 xpub6Crt4fcfpnrNxW45MzuV626z4fjddsuFGwRn1DXdpwnDkBMR12GKdBzW8euDqLSqRRv2eZmcJy8FSQLWEosC6wFZAZEv3FJMtvZ7W1CkQDi
external addresses m/49'/0'/0'/0 xpub6FQFAscJgwd8MXCcAT8A1hgx9vigrgVoXVNTAKHj2aK3NR2Zf1CbFNXD8G8X9dspGXLY9eiEzBWaypr24owJ8r1aTKgMbUZoTnQ36bBwQB3
m/49'/0'/0'/0/0 35SrGbUt9FpfA6xqKMpNaiTNyeuXagBi7Y 0.00000000 new L4TDPLYgd77GcHWdLTCEhqqd3GM15Wp7PX7dw1YeyCeRb326hM8K
m/49'/0'/0'/0/1 39hc2xfA6i9kWZdXMwH4Pd9dWUvDKocGd3 0.00000000 new L26Y8v6fU3Nx8yaRhnkKAq3wi4TkaR5BgEXuDQNmR2nv2v7kVCd9
m/49'/0'/0'/0/2 371MJcjFG4cEpz8RVdYb1L8PkA9tZYySGZ 0.00000000 new KyLza1kdozCyGwt6rkwkhshaBHS8hhciB6mnneczrxtFYXTNeyYV
m/49'/0'/0'/0/3 39eTy635wLCyBbphUTNnSB2V9LnvgdndNo 0.00000000 new KyKugtGLD1RpA8ZURCPqJ74kWyh26JBnfPG1TtjzmBoS5E3wzWJK
m/49'/0'/0'/0/4 33T8eNr54maWNZYQjoZwpLA2HN4UJB2Gk7RJaLVb 0.00000000 new L3yjfeVyBCwTgUXpdPNKPK7RBQ6Xvc17LThvF3zKM2pQkWpEEcbo
m/49'/0'/0'/0/5 35kJoTSxHtQbKUg2jvjDVqcY9iXoH2cTqD 0.00000000 new L1QXi1KjVyTFQZGWeybjnnSN3sieYGeTQtTiYrwLJmJvhQ7EBzVL
Balance: 0.00000000
internal addresses m/49'/0'/0'/1
Balance: 0.00000000
Balance for mixdepth 0: 0.00000000
mixdepth 1 xpub6Crt4fcfpnrP2GZnVuT1qi9aw9cpCuXcnGEjAKhaoWAHq5M4pWX64DNio3XHirY5uTCZCi6vTmaLjU5YQXbVsTjyEdCE2zn3S2fzBNFjxs8
external addresses m/49'/0'/1'/0 xpub6E2EnYy6yBXvE9U1nR5sSH58YiwbsKFZzaMkgMY5jrt2XFe4D5HVwikeTWyjuoczjQhJNezkwxrKAbUPMEDYHmbiaaiEAeXcL1yAcEAqtd7
m/49'/0'/1'/0/0 3DdhEr9GCoMDVRLNGAwi9rb8F4HQX8newY 0.00000000 new KzNosXo1sDfSJr7JcyqwYqGzTKTgAeQ9iEfiWA5YVE3Y6Tn3iCJs
mixdepth 0 xpub6CMAJ67vZWVXuzjzYXUoJgWrmuvFRiqiUG4dwoXNFmJtpTH3WgviANNxGyZYo27zxbMuqhDDym6fnBxmGaYoxr6LHgNDo1eEghkXHTX4Jnx
external addresses m/84'/0'/0'/0 xpub6FFUn4AxdqFbnTH2fyPrkLreEkStNnMFb6R1PyAykZ4fzN3LzvkRB4VF8zWrks4WhJroMYeFbCcfeooEVM6n2YRy1EAYUvUxZe6JET6XYaW
m/84'/0'/0'/0/0 bc1qt493axn3wl4gzjxvfg03vkacre0m6f2gzfhv5t 0.00000000 new Kyx53Zaq35EEPgCkA8bCf2GkmtMjSt261LznWJACb9NzwL8gE9zF
m/84'/0'/0'/0/1 bc1q2av9emer8k2j567yzv6ey6muqkuew4nh4rl85q 0.00000000 new KwY2ZANdevBVhdV1KxuadFe9tWoHvZGB2o1qLzgWB9uDgaZQhfPj
m/84'/0'/0'/0/2 bc1qggpg0q7cn4mpe98t29wte2rfn2rzjtn3zdmqye 0.00000000 new L5R9TD3c9NyV2Skjxhc58Gem3fhorfRrSTmMxd1JxEByFZifiuKX
m/84'/0'/0'/0/3 bc1qnnkqz8vcdjan7ztcpr68tyec7dw2yk8gjnr9ze 0.00000000 new Kxmj5YQ6V4j4jMjr3uK8kHnaDLSCuLao8Yyvn2e5pS4SR4ueCEJ6
m/84'/0'/0'/0/4 bc1qud5s2ln88ktg83hkr6gv9s576zvt249qn2lepx 0.00000000 new L2MZPx36cVTQCntDzwJF3AAYJroHEySCfBTG3o2bMCH1aDPjZS3y
m/84'/0'/0'/0/5 bc1qw0lhq7xlhj7ww2jdaknv23vcyhnz6qxg23uthy 0.00000000 new L3zrKnqxYDRDHLS3ey4a3BYkMtYPKj2eNAruiJ8SSRDA9tqceHSZ
Balance: 0.00000000
internal addresses m/84'/0'/0'/1
Balance: 0.00000000
Balance for mixdepth 0: 0.00000000
mixdepth 1 xpub6CMAJ67vZWVXyTJEaZndxZy9ACUufsmNuJwp9k5dHHKa22zQdsgALxXvMRFSwtvB8BRJzsd8h17pKqoAyHtkBrAoSqC9AUcXB1cPrSYATsZ
external addresses m/84'/0'/1'/0 xpub6FNSLcHuGnoUbaiKgwXuKpfcbR63ybrjaqHCudrma13NDqMfKgBtZRiPZaHjSbCY3P3cgEEcdzZCwrLKXeT5jeuk8erdSmBuRgJJzfNnVjj
m/84'/0'/1'/0/0 bc1qhrvm7kd9hxv3vxs8mw2arcrsl9w37a7d6ccwe4 0.00000000 new KxpBewNsVCSBktvFUPhZLEaXB4pcMwpzWdaEZ1BYRtVK9waeNLbU
.... etc
```
The above method (`-p`) still requires synchronizing the JoinMarket wallet. In the case where this isn't possible, individual private keys can still be exported:
(jmvenv)$python wallet-tool.py -H "m/49'/0'/4'/0/0" wallet.jmdat dumpprivkey
(jmvenv)$python wallet-tool.py -H "m/84'/0'/4'/0/0" wallet.jmdat dumpprivkey
Enter wallet decryption passphrase:
L1YPrEGNMwwfnvzBfAiPiPC4zb5s6Urpqnk88zNHgsYLHrq2Umss
@ -381,11 +384,11 @@ An example of the different identities being used is to not leak a lower limit o
#### BIP32 Structure
m - generated from seed
m/49' - purpose: this is specified by [BIP49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki) for P2SH-wrapped segwit P2WPKH addresses
m/49'/0' - coin type 0 : see [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) which specifies this as the coin type for Bitcoin mainnet
m/49'/0'/n' - nth mixing depth (nth account) (as per BIP44)
m/49'/0'/n'/0/k - kth external address, for mixing depth n
m/49'/0'/n'/1/k - kth internal address, for mixing depth n
m/84' - purpose: this is specified by [BIP84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) for p2wpkh native segwit addresses
m/84'/0' - coin type 0 : see [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) which specifies this as the coin type for Bitcoin mainnet
m/84'/0'/n' - nth mixing depth (nth account) (as per BIP44)
m/84'/0'/n'/0/k - kth external address, for mixing depth n
m/84'/0'/n'/1/k - kth internal address, for mixing depth n
Note that the quote (') indicates hardened derivation. See [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) for technical details.

8
docs/YIELDGENERATOR.md

@ -24,14 +24,14 @@ Open one of the two built-in yield generators: `yield-generator-basic.py` or `yg
txfee = 1000
cjfee_a = 2000
cjfee_r = '0.0002' # 0.02% fee
ordertype = 'sw0reloffer'
ordertype = 'reloffer'
minsize = int(1.2 * txfee / float(cjfee)) #minimum size is such that you always net profit at least 20% of the miner fee
Meaning of fields:
+ txfee. The yield generators contribution to the miner fee.
+ ordertype. One of 'swreloffer', 'swabsoffer', 'sw0reloffer', 'sw0absoffer'.
+ cjfee_r. Your offered coinjoin fee as a fraction of the coinjoin amount (for 'swreloffer', 'sw0reloffer'). Takers pay this to you.
+ cjfee_a. Your offered coinjoin fee as an absolute number of satoshis (for 'swabsoffer', 'sw0absoffer')
+ ordertype. One of 'reloffer', 'absoffer'
+ cjfee_r. Your offered coinjoin fee as a fraction of the coinjoin amount (for 'reloffer'). Takers pay this to you.
+ cjfee_a. Your offered coinjoin fee as an absolute number of satoshis (for 'absoffer').
## Keeping Track of Returns

4
docs/tumblerguide.md

@ -204,7 +204,7 @@ This tweaking process is repeated as many times as necessary until the transacti
## How often do retries occur?
This is hardcoded currently to `20 * maker_timeout_sec`, the figure 20 being hardcoded is due to me not wanting yet another config variable, although that could be done of course. This is the rate at which the stall monitor wakes up in the client protocol, the setting is in the code [here](https://github.com/AdamISZ/joinmarket-clientserver/blob/master/jmclient/jmclient/client_protocol.py#L87). Note that by default this is fairly slow, 10 minutes.
This is hardcoded currently to `20 * maker_timeout_sec`, the figure 20 being hardcoded is due to me not wanting yet another config variable, although that could be done of course. This is the rate at which the stall monitor wakes up in the client protocol, the setting is in the code [here](https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/acc00fc6f5a1cd1f21052c5af06cd06e78c6edda/jmclient/jmclient/client_protocol.py#L359-L363). Note that by default this is fairly slow, 10 minutes.
<a name="restarts" />
@ -221,7 +221,7 @@ This can of course be implemented in, say, a shell script (just add --restart to
## Possible failure vectors - crash or shutdown
* **Failure to source commitment** - if there is no *unused* PoDLE commitment available, the script terminates as even with tweaks this condition will not change. This *could* be changed to allow dynamic update of the `commitments.json` file (adding external utxos), but I didn't judge that to be the right choice for now. On the other hand, as was noted above, if the commitments are simply too young, the script will keep tweaking and retrying. I recommend using the `add-utxo.py` script to prepare external commitments in advance of the run for more robustness, although it shouldn't be necessary for success.
* **Network errors** - this is the biggest unknown for now; since this has not been tested in a sufficiently wide variety of network conditions, it's possible that the IRC reconnection fails in case of drop, or perhaps even crashes.
* **Network errors** - this should not cause a problem. Joinmarket handles network interruptions to its IRC communications quite robustly.
* **Insufficient liquidity**. This is a tricky one - particulary for sweeps, if the number of potential counterparties is low, and if some of them are deliberately non-responsive, you may run out of counterparties. Currently the script will simply keep retrying indefinitely. **Use a reasonably high -N value** - I think going much below 5 is starting to introduce risk, so values like `-N 6 1` should be OK, but `-N 3 1` is dubious. Force-quitting after a very long timeout is conceivable, but obviously a slightly tricky/impractical proposition.
Note that various other failure vectors will not actually cause a problem, such as the infamous "txn-mempool-conflict"; tweaking handles these cases.

14
docs/wallet-upgrade.md

@ -1,14 +0,0 @@
A new wallet format has been introduced. Old wallets require conversion.
In order to convert your existing wallet to the new format you can use the
included conversion tool at `scripts/convert_old_wallet.py`.
usage:
python convert_old_wallet.py full/path/to/wallets/wallet.json
This will place the newly converted `wallet.jmdat` file in the existing
joinmarket `wallets/` directory. The wallet name will be adopted accordingly
if it differs from `wallet`.
There is no need to move funds to the new wallet. All your funds, addresses,
private keys, history and also your seed will be retained.

13
jmclient/jmclient/taker.py

@ -506,8 +506,19 @@ class Taker(object):
self.utxo_tx = [u for u in sum(self.utxos.values(), [])]
self.outputs.append({'address': self.coinjoin_address(),
'value': self.cjamount})
# pre-Nov-2020/v0.8.0: transactions used ver 1 and nlocktime 0
# so only the new "pit" (using native segwit) will use the updated
# version 2 and nlocktime ~ current block as per normal payments.
# TODO makers do not check this; while there is no security risk,
# it might be better for them to sanity check.
if self.wallet_service.get_txtype() == "p2wpkh":
n_version = 2
locktime = compute_tx_locktime()
else:
n_version = 1
locktime = 0
self.latest_tx = btc.make_shuffled_tx(self.utxo_tx, self.outputs,
version=2, locktime=compute_tx_locktime())
version=n_version, locktime=locktime)
jlog.info('obtained tx\n' + btc.human_readable_transaction(
self.latest_tx))

2
jmclient/jmclient/wallet.py

@ -1366,7 +1366,7 @@ class SNICKERWalletMixin(object):
# version and locktime as currently specified in the BIP
# for 0/1 version SNICKER.
tx = btc.make_shuffled_tx([our_input, their_input], outputs,
version=2, locktime=compute_tx_locktime())
version=2, locktime=0)
# we need to know which randomized input is ours:
our_index = -1
for i, inp in enumerate(tx.vin):

25
jmclient/jmclient/yieldgenerator.py

@ -188,7 +188,7 @@ class YieldGeneratorBasic(YieldGenerator):
return self.wallet_service.get_internal_addr(cjoutmix)
def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='sw0reloffer',
def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='reloffer',
nickserv_password='', minsize=100000, gaplimit=6):
import sys
@ -222,20 +222,19 @@ def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='sw0reloff
wallet_name = args[0]
ordertype = options.ordertype
txfee = options.txfee
if ordertype in ('reloffer', 'swreloffer', 'sw0reloffer'):
if ordertype == 'reloffer':
if options.cjfee != '':
cjfee_r = options.cjfee
# minimum size is such that you always net profit at least 20%
#of the miner fee
minsize = max(int(1.2 * txfee / float(cjfee_r)), options.minsize)
elif ordertype in ('absoffer', 'swabsoffer', 'sw0absoffer'):
elif ordertype == 'absoffer':
if options.cjfee != '':
cjfee_a = int(options.cjfee)
minsize = options.minsize
else:
parser.error('You specified an incorrect offer type which ' +\
'can be either swreloffer, sw0reloffer, ' +\
'swabsoffer, or sw0absoffer')
'can be either reloffer or absoffer')
sys.exit(EXIT_ARGERROR)
nickserv_password = options.password
@ -257,8 +256,22 @@ def ygmain(ygclass, txfee=1000, cjfee_a=200, cjfee_r=0.002, ordertype='sw0reloff
wallet_service.sync_wallet(fast=not options.recoversync)
wallet_service.startService()
txtype = wallet_service.get_txtype()
if txtype == "p2wpkh":
prefix = "sw0"
elif txtype == "p2sh-p2wpkh":
prefix = "sw"
elif txtype == "p2pkh":
prefix = ""
else:
jlog.error("Unsupported wallet type for yieldgenerator: " + txtype)
sys.exit(EXIT_ARGERROR)
ordertype = prefix + ordertype
jlog.debug("Set the offer type string to: " + ordertype)
maker = ygclass(wallet_service, [options.txfee, cjfee_a, cjfee_r,
options.ordertype, options.minsize])
ordertype, options.minsize])
jlog.info('starting yield generator')
clientfactory = JMClientProtocolFactory(maker, proto_type="MAKER")

6
jmclient/test/test_coinjoin.py

@ -137,7 +137,7 @@ def test_simple_coinjoin(monkeypatch, tmpdir, setup_cj, wallet_cls):
makers = [YieldGeneratorBasic(
wallet_services[i],
[0, 2000, 0, 'swabsoffer', 10**7]) for i in range(MAKER_NUM)]
[0, 2000, 0, 'sw0absoffer', 10**7]) for i in range(MAKER_NUM)]
create_orders(makers)
orderbook = create_orderbook(makers)
@ -182,7 +182,7 @@ def test_coinjoin_mixdepth_wrap_taker(monkeypatch, tmpdir, setup_cj):
cj_fee = 2000
makers = [YieldGeneratorBasic(
wallet_services[i],
[0, cj_fee, 0, 'swabsoffer', 10**7]) for i in range(MAKER_NUM)]
[0, cj_fee, 0, 'sw0absoffer', 10**7]) for i in range(MAKER_NUM)]
create_orders(makers)
orderbook = create_orderbook(makers)
@ -238,7 +238,7 @@ def test_coinjoin_mixdepth_wrap_maker(monkeypatch, tmpdir, setup_cj):
cj_fee = 2000
makers = [YieldGeneratorBasic(
wallet_services[i],
[0, cj_fee, 0, 'swabsoffer', 10**7]) for i in range(MAKER_NUM)]
[0, cj_fee, 0, 'sw0absoffer', 10**7]) for i in range(MAKER_NUM)]
create_orders(makers)
orderbook = create_orderbook(makers)
assert len(orderbook) == MAKER_NUM

16
scripts/yg-privacyenhanced.py

@ -15,14 +15,14 @@ from jmclient import YieldGeneratorBasic, ygmain, jm_single
"""THESE SETTINGS CAN SIMPLY BE EDITED BY HAND IN THIS FILE:
"""
ordertype = 'swreloffer' # [string, 'swreloffer', 'swabsoffer', 'sw0reloffer', 'sw0absoffer'] / which fee type to actually use
ordertype = 'reloffer' # [string, 'reloffer' or 'absoffer'], which fee type to actually use
cjfee_a = 500 # [satoshis, any integer] / absolute offer fee you wish to receive for coinjoins (cj)
cjfee_r = '0.00002' # [percent, any str between 0-1] / relative offer fee you wish to receive based on a cj's amount
cjfee_factor = 0.1 # [percent, 0-1] / variance around the average fee. Ex: 200 fee, 0.2 var = fee is btw 160-240
cjfee_r = '0.00002' # [fraction, any str between 0-1] / relative offer fee you wish to receive based on a cj's amount
cjfee_factor = 0.1 # [fraction, 0-1] / variance around the average fee. Ex: 200 fee, 0.2 var = fee is btw 160-240
txfee = 100 # [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions
txfee_factor = 0.3 # [percent, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200
txfee_factor = 0.3 # [fraction, 0-1] / variance around the average fee. Ex: 1000 fee, 0.2 var = fee is btw 800-1200
minsize = 100000 # [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded
size_factor = 0.1 # [percent, 0-1] / variance around all offer sizes. Ex: 500k minsize, 0.1 var = 450k-550k
size_factor = 0.1 # [fraction, 0-1] / variance around all offer sizes. Ex: 500k minsize, 0.1 var = 450k-550k
gaplimit = 6
# end of settings customization
@ -39,9 +39,9 @@ class YieldGeneratorPrivacyEnhanced(YieldGeneratorBasic):
# We publish ONLY the maximum amount and use minsize for lower bound;
# leave it to oid_to_order to figure out the right depth to use.
f = '0'
if ordertype in ['swreloffer', 'sw0reloffer']:
if self.ordertype in ['swreloffer', 'sw0reloffer']:
f = self.cjfee_r
elif ordertype in ['swabsoffer', 'sw0absoffer']:
elif self.ordertype in ['swabsoffer', 'sw0absoffer']:
f = str(self.txfee + self.cjfee_a)
mix_balance = dict([(m, b) for m, b in iteritems(mix_balance)
if b > self.minsize])
@ -60,7 +60,7 @@ class YieldGeneratorPrivacyEnhanced(YieldGeneratorBasic):
randomize_maxsize = int(random.uniform(possible_maxsize * (1 - float(size_factor)),
possible_maxsize))
if ordertype == 'swabsoffer':
if self.ordertype == 'swabsoffer':
randomize_cjfee = int(random.uniform(float(cjfee_a) * (1 - float(cjfee_factor)),
float(cjfee_a) * (1 + float(cjfee_factor))))
randomize_cjfee = randomize_cjfee + randomize_txfee

13
scripts/yield-generator-basic.py

@ -5,17 +5,18 @@ from jmclient import YieldGeneratorBasic, ygmain
"""THESE SETTINGS CAN SIMPLY BE EDITED BY HAND IN THIS FILE:
"""
txfee = 100
cjfee_a = 500
cjfee_r = '0.00002'
ordertype = 'sw0reloffer' # [string, 'swreloffer', 'sw0reloffer', 'swabsoffer', 'sw0absoffer']
ordertype = 'reloffer' # [string, 'reloffer' or 'absoffer'], which fee type to actually use
cjfee_a = 500 # [satoshis, any integer] / absolute offer fee you wish to receive for coinjoins (cj)
cjfee_r = '0.00002' # [fraction, any str between 0-1] / relative offer fee you wish to receive based on a cj's amount
txfee = 100 # [satoshis, any integer] / the average transaction fee you're adding to coinjoin transactions
nickserv_password = ''
max_minsize = 100000
minsize = 100000 # [satoshis, any integer] / minimum size of your cj offer. Lower cj amounts will be disregarded
gaplimit = 6
if __name__ == "__main__":
ygmain(YieldGeneratorBasic, txfee=txfee, cjfee_a=cjfee_a,
cjfee_r=cjfee_r, ordertype=ordertype,
nickserv_password=nickserv_password,
minsize=max_minsize, gaplimit=gaplimit)
minsize=minsize, gaplimit=gaplimit)
jmprint('done', "success")

Loading…
Cancel
Save