你选择了快速安装(按照README中的`./install.sh`)(推荐),或者...

本文档提供了Joinmarket客户端服务器的安装、配置和使用说明,包括钱包管理、Bitcoin Core配置、wallet-tool.py脚本的使用、coinjoin尝试、运行Maker以及使用tumbler脚本提升隐私。内容涵盖了如何创建、资助和恢复钱包,以及如何通过coinjoin实现比特币的隐私保护。

(你要么按照 readme 中的快速安装(./install.sh)(推荐),要么按照此处进行手动安装。)

(如果你想运行 Joinmarket-Qt,请从演练开始,而不是本指南。)

目录

  1. 管理你的 Joinmarket 数据

    a. 可移植性

  2. 配置 Bitcoin Core

    a. 设置 Core 钱包(Bitcoin Core v0.21 及更高版本需要)

  3. 使用 wallet-tool.py 脚本

    a. 创建钱包

    b. 充值钱包并显示余额

    c. 直接从钱包支出(不使用 Coinjoin)

    d. 从助记词恢复钱包

    e. 从钱包恢复助记词

    f. 恢复私钥

    g. 钱包历史

    h. 导入外部私钥

    i. 什么是 BIP32 钱包结构

    j. 什么是 Gap Limit

    k. 共同签署 PSBT

  4. 尝试 coinjoin;使用 sendpayment.py

  5. 运行“Maker”或“收益生成器”

  6. 运行 tumbler 脚本以提高自有币的隐私性

<a name="data" />

管理你的 Joinmarket 数据

首先要做的事情:进入 scripts/,然后运行:

(jmvenv)$ python wallet-tool.py generate

应该会因错误而退出,因为与 Bitcoin Core 的连接未配置;我们将在下一节中介绍。 但是,第一次运行将自动创建一个数据目录。 找到新创建的文件 joinmarket.cfg,它将位于你的用户主目录下的 .joinmarket/ 中。 因此,在 Linux 上,你应该在 /home/username/.joinmarket/joinmarket.cfg 下找到它,macOS 和 Windows 类似。 你应该看到以下文件和文件夹以进行初始设置:

.joinmarket/
    joinmarket.cfg
    logs/
    wallets/
    cmtdata/

joinmarket.cfg 是 Joinmarket 的主要配置文件,其中包含许多设置,你需要编辑其中一些设置,或者至少检查一下。 这将在下面的几个部分中讨论。 wallets/ 目录是在你创建钱包后存储钱包文件的位置,扩展名(默认情况下)为 .jmdat。它们已加密并存储重要信息;没有它们,可以使用 seedphrase 恢复你的币,但会很麻烦,因此请保证文件安全。 logs/ 目录包含你运行的每个机器人(Maker 或 Taker)的日志文件,其中包含调试信息。除非你遇到问题,否则你很少需要读取这些文件;建议定期删除它们(并且永远不会有危险)。但是,此处还保存了其他日志文件,特别是名为 yigen-statement.csv 的文件,该文件记录了你的 Maker 机器人随时间推移所做的所有交易。这对于跟踪非常有用。此外,tumble 在此处有一个 TUMBLE.scheduleTUMBLE.log 文件,这些文件非常有用;不要删除它们。 cmtdata/ 目录存储你不需要读取的技术信息。

<a name="portability" />

可移植性

可以使用与上述默认目录 (~/.joinmarket/ 或等效目录) 不同的数据目录。为此,请使用标志 --datadir=/my/data/directory 运行任何 Joinmarket 脚本(有关主要脚本的说明,请参见下文)。 然后将在那里创建上述目录结构。如果你将钱包文件从一个目录移动到另一个目录,它将可以正常工作,只要你使用相同的 Bitcoin Core 实例即可。

稍微困难的情况是移动到新机器和/或新的 Bitcoin Core 实例。在那里,除了需要更改 BLOCKCHAIN 配置设置(请参阅下一节)之外,当你将 .jmdat 文件移动到新设置时,你还会遇到另一个障碍。 由于新的 Bitcoin Core 实例未导入地址,因此你需要对区块链进行一定范围的块的重新扫描。

最坏的情况是,如果你仅从 seedphrase 恢复并在新的 Core 实例上恢复;那么你不仅没有导入地址,而且 Joinmarket 必须搜索地址以查找所有用法,这可能会很棘手,并且理论上可能需要多次重新扫描。如果钱包被大量使用,请使用 wallet-tool.py--recoversync 选项并使用较大的 gap limit (-g)。

<a name="configure" />

配置 Bitcoin Core。

使用 Joinmarket 需要 Bitcoin Core;请注意,该节点可以被裁剪。

请注意,如果你自己编译 Core,则它必须具有钱包支持(默认设置),但不需要 Qt。

为 Core 配置 Joinmarket 不再需要任何 walletnotify 设置。

在上面描述的 joinmarket.cfg 文件中,编辑此部分(省略注释; 确实要阅读它们):

[BLOCKCHAIN]
rpc_user = yourusername-as-in-bitcoin.conf
rpc_password = yourpassword-as-in-bitcoin.conf
rpc_host = localhost #default usually correct
rpc_port = 8332 # default for mainnet

请注意,你还可以通过在此部分中设置变量 rpc_cookie_file 到该文件的位置来使用 cookie 文件,作为使用用户/密码的一种替代方法。

<a name="setting-core-wallet" />

设置 Core 钱包(Bitcoin Core v0.21 及更高版本需要)

注意:虽然对于 0.21 之前的 Bitcoin Core 版本来说,此步骤不是严格必需的,但仍然建议这样做。

这一点经常使人们感到困惑。Joinmarket 有自己的钱包,其中包含加密和密钥存储,与 Bitcoin Core 分开, 但是它将地址作为仅观看存储在 Bitcoin Core 钱包中,并且与 Bitcon Core 的相关 rpc 调用始终指定 他们正在与之通信的钱包。因此,强烈建议使用此功能,因为它隔离了存储在 Bitcoin Core 中的那些仅观看地址, 来自你可能拥有的该 Core 实例的任何其他用途。

如果你不这样做,并且有一个,Joinmarket 将使用默认的 Core 钱包 wallet.dat 在其中存储这些仅观看地址。 如果没有,则启动将失败并显示 JsonRpcError Wallet file verification failed. Failed to load database path '…'. Path does not exist.。 请务必按照以下步骤操作。

bitcoind 运行的情况下,执行:

bitcoin-cli -named createwallet wallet_name=jm_wallet disable_private_keys=true

“jm_wallet”名称只是一个示例。你可以设置任何名称。除了此 bitcoin-cli 命令之外:你还可以在 bitcoin.conf 中设置带有 wallet=.. 的行,然后再启动 Core(有关详细信息,请参阅 Bitcoin Core 文档)。

在 Bitcoin Core 中创建钱包后,应在 joinmarket.cfg 中进行设置:

[BLOCKCHAIN]
...
...
rpc_wallet_file= jm_wallet

然后重试我们上面提到的 generate 命令;现在应该没有错误(请参阅下面)。

如果仍然收到 rpc 连接错误,请确保首先可以使用命令行连接到你的 Core 节点。

<a name="wallet-tool" />

使用 wallet-tool.py 脚本

本节将引导你完成使用 wallet-tool.py 脚本创建、充值、恢复和显示有关 Joinmarket 钱包的信息的基础知识。提醒一下,此时,你应该在命令行上,并且在 Joinmarket 目录的 scripts/ 子目录中。

Joinmarket 钱包是分层且确定性的,可以完全从单个种子中恢复。在任何时候,你都可以在命令行上使用 python wallet-tool.py --help 来获取所有选项。我们现在将介绍所有主要功能:

<a name="generate" />

创建钱包

使用 generate 方法运行 wallet-tool.py。将 12 个单词的种子写在纸上。

(jmvenv)$ python wallet-tool.py generate
Write down this wallet recovery mnemonic on paper:

matter aim multiply december stove march wolf nuclear yard boost worth supreme

Enter wallet encryption passphrase:
Reenter wallet encryption passphrase:
Input wallet file name (default: wallet.jmdat):
saved to wallet.jmdat
$

到目前为止,你只是创建了钱包。但是要执行下一步,你需要查看地址。 运行 python wallet-tool.py wallet.jmdat(或将钱包名称替换为你选择的任何名称)。你将收到以下消息:

如果从备份种子恢复现有钱包,请使用 -rescan 重新启动 Bitcoin Core 或使用 bitcoin-cli rescanblockchain 否则,只需重新启动此 joinmarket 应用程序。

请注意,在这里你不需要重新扫描,因为你没有“恢复现有钱包”,而是创建新钱包。因为它是新的,所以还没有使用任何地址。只有在地址被使用时,才需要重新扫描(或使用如上所述的 rescanblockchain,顺便说一句,这可能是更有效的重新扫描方式)...

<a name="funding" />

充值钱包并显示余额

...因此,忽略这一点,只需再次运行 python wallet-tool.py wallet.jmdat。你应该得到如下所示的大量输出:

JM wallet
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: 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
internal addresses  m/84'/0'/1'/1
Balance:    0.00000000
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   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/84'/0'/3'/1
Balance:    0.00000000
Balance for mixdepth 3: 0.00000000
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/84'/0'/4'/1
Balance:    0.00000000
Balance for mixdepth 4: 0.00000000
Total balance:  0.00000000

每个外部分支的 BIP32 xpub 密钥都会显示,以防需要。 还显示了 BIP32 推导路径;对于 Joinmarket,它们由 BIP84 定义;有关更多信息,请参见下面

如果在 ~/.joinmarket/joinmarket.cfg 文件的 [POLICY] 部分中设置 native = false,你将使用 '3' 地址创建一个钱包,该地址是 p2sh 包装的隔离见证,而不是 'bc1' 地址;它使用 BIP49 而不是 BIP84,但可以类似地恢复(就交易费用而言,它稍微贵一些;这是 Joinmarket 在 0.8.0 之前的默认设置)。

比特币应发送到空的外部地址(有时称为接收地址)。你会注意到 在上面,虽然也有内部地址的字段,但它们是空的。那是因为默认情况下隐藏了零余额的内部地址(也称为找零地址)。使用'displayall'作为第二个参数将显示钱包中的所有地址,包括已使用的空地址。

在为钱包充值之前,请阅读此处的说明。

充值后,再次运行 python wallet-tool.py wallet.jmdat,输入你的密码,你应该会看到存入的币。

<a name="spending" />

直接从钱包支出(不使用 Coinjoin)

请注意,Joinmarket 的钱包支持支出到所有地址类型,包括传统地址('1')、P2SH 地址('3')和 bech32 地址('bc1')。要了解有关如何在不使用 CoinJoin 的情况下直接支出的更多信息,请参见此处

<a name="recover" />

从助记词恢复钱包

如果加密钱包文件丢失,请使用 12 个单词的种子通过运行 wallet-tool.py 并以 'recover' 作为第一个参数来恢复:

(jmvenv)$python wallet-tool.py recover
Input mnemonic recovery phrase: matter aim multiply december stove march wolf nuclear yard boost worth supreme
Input mnemonic extension, leave blank if there isnt one:
Enter wallet file encryption passphrase:
Reenter wallet file encryption passphrase:
Input wallet file name (default: wallet.jmdat):
Write down this wallet recovery mnemonic

matter aim multiply december stove march wolf nuclear yard boost worth supreme

Recovered wallet OK
救命!我恢复了,但有些钱不见了

尝试将间隙限制从其默认值 6 向上增加。如果你运行 yield generator 机器人一段时间(请参阅下文),则更有可能发生这种情况。

(jmvenv)$ python wallet-tool.py -g 50 my-wallet-file.jmdat

另一种可能的原因是你在旧钱包中使用的 tumbler 脚本的 mixdepth 数超过了 5。在这种情况下,请增加最大 mixdepth:

(jmvenv)$ python wallet-tool.py -m 15 recover

请注意,你必须在开始时做出该决定,即使用 recover 方法为这个旧种子创建新的钱包文件时。因此,如果你认为钱包已被大量使用且 mixdepth 数量很大,请谨慎行事并使用更大的 -m 值。如果你不指定它,它将仅使用默认值 5。

<a name="mnemonic" />

恢复钱包的助记词密码

showseed 命令将显示现有钱包文件的助记词,以防你忘记了它。强烈建议保留该短语的书面备份,以免忘记!

(jmvenv)$ python wallet-tool.py wallet.jmdat showseed

<a name="privkeys" />

恢复私钥

可以在 Trezor、Electrum 或许多其他钱包中恢复 Joinmarket 钱包,因为它使用 BIP84。但请注意,出于隐私原因,这并不理想(如果你使用你的地址联系服务器),而且由于 Joinmarket 使用多个帐户(=mixdepth),因此可能比预期的更困难。

在困难的恢复情况下,可以使用 -p 命令行标志来打印私钥。非常小心地考虑此高级用法:

...
JM wallet
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

以上方法 (-p) 仍然需要同步 JoinMarket 钱包。如果不可能,仍然可以导出单个私钥:

(jmvenv)$python wallet-tool.py -H "m/84'/0'/4'/0/0" wallet.jmdat dumpprivkey
Enter wallet decryption passphrase:
L1YPrEGNMwwfnvzBfAiPiPC4zb5s6Urpqnk88zNHgsYLHrq2Umss

...使用如上所述的输出中指定的派生路径(m/...);请注意需要用双引号将其引起来。

<a name="history" />

钱包历史

可以显示钱包交易历史。 打印每个交易的摘要。 如果你安装了 numpy/scipy,它还会计算你获得的实际利率,就好像你的 yield-generator 是一个储蓄帐户一样。

(jmvenv)$ python wallet-tool.py wallet.jmdat history
tx# timestamp type amount/btc balance-change/btc balance/btc coinjoin-n total-fees utxo-count mixdepth-from mixdepth-to
    0 2016-04-20 21:37 deposit     0.15000000 +0.15000000 0.15000000  # #             1  #  0
    1 2016-04-20 22:22 cj internal 0.02115585 +0.00006341 0.15006341  3 #             2  0  1
    2 2016-04-20 23:27 cj internal 0.15046475 +0.00021085 0.15027426  4 #             3  0  1
    3 2016-04-21 23:45 cj internal 0.01209051 +0.00003159 0.15030585  5 #             4  0  1
    4 2016-04-21 00:07 cj internal 0.03120432 +0.00006307 0.15036892  3 #             5  1  2
    5 2016-04-21 00:07 cj internal 0.05538475 +0.00017932 0.15054824  4 #             6  1  2
     2016-04-21 18:55 best block is 000000000000000005009c707b2427224c784c6224a5c44ee449d93b727739e7
continuously compounded equivalent annual interest rate = 0.459494243045 %
(as if yield generator was a bank account)
$

你可以创建一个 csv 文件,以便使用电子表格软件打开:

(jmvenv)$ python wallet-tool.py --csv wallet.jmdat history > history.csv

<a name="importprivkeys" />

导入外部私钥

可以使用 'importprivkey' 方法将单独的私钥导入到 JoinMarket 钱包中。可以通过逗号或空格分隔来导入多个私钥。使用 -M 标志来控制将私钥导入到哪个 mixing depth 中。请注意,像这样处理原始私钥是危险的。 在使用之前,你应该阅读警告并理解这种非直观的行为。 参考这里这里页面。 如果可以,最好避免导入私钥。

        (jmvenv)$ python wallet-tool.py -m 0 example.jmdat importprivkey
        Enter wallet decryption passphrase: 
        WARNING: This imported key will not be recoverable with your 12 word mnemonic seed. Make sure you have backups.
        WARNING: Handling of raw ECDSA bitcoin private keys can lead to non-intuitive behaviour and loss of funds.
          Recommended instead is to use the 'sweep' feature of sendpayment.py 
        Enter private key(s) to import: KzHJDZrSmmwkZKdLNS8L91qGsL9By6b48deaZRExBg4vAiyiBE7V Kxo3mHpUcx6KcLsyGTETh3ZJHEeU73tNCwYM1Yk7MMoTcW4jZ7Mi L3SdjpTu8tGdtht74wwsUX37bqGmr44AoyvZSqvrhTieN2GhbP7e
        Private key(s) successfully imported
        $

<a name="structure" />

什么是 BIP32 钱包结构

Mixing Depth 概念

JoinMarket 的目的是提高隐私性。合并的交易输入会损害隐私性,因为它们提供了共同所有权的证据。每个 mixing depth 都是一个不同的身份,币永远不会在相同的 mixing depth 的交易中合并,但可能会在 mixing depth 内部合并。币通过 coinjoins 在 mixing depth 之间移动。 找零输出保持在相同的 mixing depth 中。这可以防止找零输出在后续交易中与 coinjoin 输出合并的情况,这将使 coinjoin 很容易被解除混合。

使用不同身份的一个例子是不泄露你的钱包余额的下限。想象一下,如果有人支付你 10 美元,并看到它与 100 万美元合并,他们可以推断出你至少拥有那么多。如果这两个付款转到不同的混合级别,那么这种分析就会变得更加困难。当币通过 coinjoin 向上移动混合级别时,它们的身份变得更加不确定。为了引入更多的不确定性,让币被更多的混合级别分隔开。例如,第 0 级的币和第 1 级的第二个币将与它们之间的一组 coinjoins 合并,第 5 级的第二个币将与 5 组 coinjoins 合并。

BIP32 结构

m - 从种子生成 m/84' - 目的:这由 BIP84 指定,用于 p2wpkh 原生隔离验证地址 m/84'/0' - 币种类型 0:参见 BIP44,它将其指定为比特币主网的币种类型 m/84'/0'/n' - 第 n 个 mixing depth(第 n 个账户)(按照 BIP44) m/84'/0'/n'/0/k - 第 k 个外部地址,对于 mixing depth n m/84'/0'/n'/1/k - 第 k 个内部地址,对于 mixing depth n

请注意,引号 (') 表示推导。有关技术细节,请参见 BIP32

<a name="gaplimit" />

什么是 Gap Limit?

使用确定性钱包,你可以从初始种子创建比特币地址和私钥序列。此列表每次生成时都相同,这意味着可以通过仅保存初始种子来备份整个钱包。

你可以根据需要创建任意数量的地址,但并非所有地址都会出现在区块链上。例如,我可以专门为你创建一个地址,让你给我 1,000,000 BTC。这(唉!)可能不会被使用,因此可能永远不会出现在区块链上。

当你启动 JoinMarket 时,它不知道哪个是最后一个使用的地址。因此,你从头开始,看看区块链上有什么。然后,你在序列中查找下一个。gap limit 是你在放弃并停止查找之前接受的未命中次数。相同的概念也用于其他确定性钱包,如 Electrum。

<a name="psbt" />

共同签署 PSBT

Joinmarket 现在(0.8.1+ 版本)具有(有限的)PSBT 支持。你可以从另一个来源获取 PSBT,该来源创建了一个交易,花费了你的一些 UTXO 以及其他 UTXO,并对其进行共同签署(例如,自定义 coinjoin)。如果你的钱包识别出这些币属于你,它将签署它们并呈现准备广播的交易(如果签名已完成)。使用此功能时要小心。目前,这是一种手动过程;在广播交易之前,你必须仔细阅读所提供的信息,以确保你没有花费你不打算花费的币。此功能应该适用于原生和 p2sh 隔离验证钱包(但未经过非隔离验证测试)。对于在其他钱包中创建此类 PSBT,在在此处共同签署它们之前,你可能需要使用帐户(mixdepth)的 xpub,如 wallet-tool.py 默认方法 display 的输出中所示;对于分析正在发生的事情的一般分析,请不要忘记你可以使用 wallet-tool.py 方法 showutxos

语法是:

python wallet-tool.py mywalletname.jmdat signpsbt &lt;base64-psbt>

请注意,你只需要 PSBT 本身,你不需要例如 mixdepth 或其他元数据,该工具将自行判断此钱包是否能够共同签署。如果它没有以“finalized”(完全签名)的 PSBT 结束,它将在任何情况下输出最新的“updated”PSBT,并告诉你它进行了多少次签名。

<a name="try-coinjoin" />

尝试 coinjoin;使用 sendpayment.py

进行单个 coinjoin 实际上并不能显着提高隐私性;因此,如果这仅仅是你的兴趣所在,你可以跳过大部分内容,然后转到 这里 来了解 tumbler 脚本;但请在此处阅读如何从钱包中花费币。

单个 coinjoin 可以使目的地(付款)输出不明确,并且可以显着降低自动化的区块链监控。我们建议在进行付款时伺机使用这些,但绝不能依赖于这样做获得的任何特定隐私增益。

可以使用脚本 sendpayment.py 完成单个 coinjoin。与所有 Joinmarket 用户脚本一样,使用 --help 查看完整的选项列表。

这是一个示例:

        (jmvenv)$ python sendpayment.py wallet.jmdat 5000000 mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c

或者你可以使用 BIP21 比特币支付 URI:

        (jmvenv)$ python sendpayment.py wallet.jmdat bitcoin:mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c?amount=0.05

这些将 5000000 satoshi (0.05btc) 发送到地址 mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c (testnet),默认情况下从文件 wallet.jmdat 中包含的钱包的默认第 0 个 mixing depth 中随机发送 8-10 个(随机)其他参与者。这将需要一些时间,因为 Joinmarket 将连接到远程消息服务器并与其他机器人进行端到端加密通信,并且你还将支付一些费用(稍后在本节中详细介绍)。

<a name="no-coinjoin-sending-funds" />

没有 coinjoin,发送资金

假设你只是想在没有 coinjoin 的情况下支付该地址。很简单,只需将交易对手的数量设置为零:

        (jmvenv)$ python sendpayment.py wallet.jmdat -N 0 5000000 mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c

当你设置 -N 0 时,诸如“sweep”和网络费用(参见下文)之类的其他选项的工作方式相同。这是你的基本钱包功能,没有 CoinJoin。

这是 CoinJoin 用法的另一个示例:

        (jmvenv)$ python sendpayment.py -N 5 -m 1 wallet.jmdat 100000000 mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c

从 mixing depth 1(第二个!)发送 1BTC(1 亿 satoshi),与五个其他方混合。

金额可以指定为比特币(如果为十进制值或带有“btc”后缀)或 satoshis(如果为整数值或带有“sat”后缀)。因此,1 BTC 可以指定为 1.0、1btc、100000000、100000000sat 或 100000000.0sat。

将金额设置为零将导致机器人进行清扫。这意味着它将清空该混合深度,计算 coinjoin 费用,以便不留下任何币。

        (jmvenv)$ python sendpayment.py -N 7 wallet.jmdat 0 mprGzBA9rQk82Ly41TsmpQGa8UPpZb2w8c

... 将 mixdepth 0(默认)中的所有币发送到目标地址,减去 coinjoin 和网络费用所需的任何金额,通过与 7 个其他方的 CoinJoin。请注意,sweep 是特别强大的 CoinJoin,因为没有留下任何更改来建立未来的联系。

费用设置

有两种不同类型的费用:比特币网络交易费用和支付给交易对手以提供 coinjoin 流动性的费用(后者是 Joinmarket 的核心思想)。

比特币网络费用。

这通过在当前目录中的 joinmarket.cfg 文件中的 [POLICY] 部分中设置 tx_fees 来控制。如果你将其设置为 1 到 1000 之间的数字,则将其视为确认的目标区块数;例如,如果你将其设置为 20,则你要求使用比特币核心认为在接下来 20 个区块内获得确认的实际费用。默认情况下为 3。如果你将其设置为大于 1000 的数字,请不要将其设置低于约 1200,它将被解释为“每千字节的交易费用中 satoshi 的数量”。1000 等于每字节 1 satoshi(忽略 vbyte 的技术细节),通常是网络上节点将转发的最低费用。请注意,Joinmarket 会在此处故意随机更改你的选择,在这种情况下,两侧更改 20%,以避免你使用完全相同的费率为所有交易添加水印。例如,如果你更喜欢使用大约 20 sats/byte 的费率,而不是依赖比特币核心对 3 或 6 个区块的估计目标,则将 tx_fees 设置为 20000。 请注意,一些流动性提供者 (Makers) 会对 tx 费用提供非常小的贡献,但主要你应该认为你必须自己支付整个比特币网络费用,作为 coinjoin(Taker)的发起者。另请注意,如果你设置了 7 个交易对手,则你实际上支付了大约 7 个正常大小的交易的费用;请注意!

关于 coinjoin sweep 的补充说明:在这种情况下,我们必须估计费用(由于没有找零输出)。有关如何控制费用的方差,请参阅 joinmarket.cfg 设置 max_sweep_fee_change 的注释,特别是对于这种情况。

CoinJoin 费用。

各个 Maker 将以不同的费率提供 CoinJoin。有些人将其费用设置为金额的百分比,而另一些人将其费用设置为固定数量的 satoshi。大多数人将其费率设置得非常低,因此在大多数(但并非所有)情况下,总体 CoinJoin 费用将低于上述比特币网络费用。在开始进行 CoinJoin 时,系统会提示你设置你愿意接受的来自一个参与者的最大相对(百分比)和绝对(satoshi 数量)费用;然后你的机器人将从至少低于其中一个限制的参与者中随机选择。请仔细阅读这些说明并相应地更新你的配置文件,以避免重复回答问题。

另请注意,你可以使用“schedule”文件,但这是更高级的,因此现在忽略它;有关更多详细信息,请参阅 scripts/ 下的 README。

<a name="run-maker" />

运行“Maker”或“收益生成器”。

请遵循此处的指南(<a href="https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/YIELDGENERATOR.md">https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/YIELDGENERATOR.md&lt;/a>)。

<a name="run-tumbler" />

运行 tumbler 脚本以提高所拥有币的隐私性。

阅读 此处 的说明。

  • 原文链接: github.com/JoinMarket-Or...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
JoinMarket-Org
JoinMarket-Org
江湖只有他的大名,没有他的介绍。