Skip to content

Instantly share code, notes, and snippets.



Last active Jan 11, 2021
What would you like to do?
Chris Belcher work diary
I keep a diary of all the work I do on bitcoin privacy.
It may also be interesting to my collaborators and donors, and anyone who wants to follow
how my projects are going (these days I'm almost exclusively working on developing
CoinSwap, see
(Note: I use the datetime format YYYY-MM-DD)
= week-2021-1-4 =
still implementing multihop coinswaps with an arbitrary number of hops
using rust's trait feature which i havent used before, so having some trouble
figure it out, thanks again to ##rust on freenode
in multihop coinswaps i implemented the SendersAndReceiversContractSigs protocol message
which is one of the biggest parts because the taker has to obtain those signatures
from different places depending on whether the previous and/or next coinswap peers
are makers or the taker itself
implemented the final SignReceiversContractTx which was also very fiddly
i implemented the entire main for-loop which obtains and relays pubkeys, transactions and
signatures to all the makers
this is hopefully the hardest part over, now just to give the hash preimage to every maker
and relay their privkeys
came up with a slightly better sequence for sending the hash preimage message to makers
= week-2020-12-28 =
writing a bit of pseduocode to figure out the best way to recode multi-hop taker
couldnt figure it out, i will try modifying the taker protocol to do a routed coinswap with 3 makers
and hopefully from that ill figure how to code it for N makers
wrote down a diagram of multi-hop coinswap with 3 makers
had some inspiration about how to code a N-hop coinswap, trying to write some pseudocode in a text file now
wrote the pseudocode which i think should work, coding it in rust now
i realize it would be useful to first implement code on the maker side which allows the taker to disconnect
the tcp connection while waiting for transactions to confirm and then later reconnect
the maker cant handle this right now, and if i code the arbitrary-multi-hop taker this way then it would be
unnecessary technical debt
after reading the maker code carefully, it looks like it already supports tcp connection reconnecting
ill change the code a bit in taker to try it out
tried it out, it works perfectly
will upload this code to the master branch on github because its useful
i came across this paper describing wormhole attacks against the lightning network
reading it because its possible a similar attack will work against routed coinswap
read the relevant section and found that the wormhole attack cant be used, for at least two reasons:
1) makers in coinswap routes dont talk directly to each other
2) payments in routed coinswap cant be cancelled without the detection (the taker will be see the mined contract transactions)
3) the taker releases the hash preimage to every maker directly and simultaneously
= week-2020-12-21 =
writing the sending and receiving of steps C and D in the protocol, which is very fiddly
finished that, writing code to wait for maker2's funding transactions to be confirmed
finished all that code, and the hash_preimage message and the private key handover message
testing multi-hop coinswaps on regtest
run up against a block, for some reason my code thinks the second maker sent an invalid signature
the sender and receiver pubkeys are mixed up for some reason
next bug: when sending hash preimage the multisig redeemscript isnt found by the maker
the receivers_multisig_redeemscripts are not found anywhere else in any debug logs
search for the `senders_contract_tx_info.multisig_redeemscript` in the logs, i bet theres a problem parsing it
wasnt that
found the bug, i accidently used maker1's public keys instead of maker2's, works now
i just the first multi-hop coinswap on regtest(!)
Currently the code is not that great, there is a lot of repeated code as the taker explicitly sends and
receives each message. The multi-hop is fixed at two hops. So will now work on rewriting the code a bit
to remove the duplication and also allow an arbitrary number of hops.
There will essentially be a for-loop which does the multi-hopping.
one thing missing from my code is the taker handling a coinswap between three makers where the
taker's pubkeys are not involved at all, this only happens with a three-maker coinswap or above
= week-2020-12-14 =
finished writing a readme for this early stage of the project
currently using rustfmt on my code for the first time
i uploaded the code i have so far:
its at the pretty early stages, e.g. theres no configuration files you have to edit things in the source
but you can create your own coinswaps on regtest or testnet
along with the IRC channel ##coinswap on the freenode network
set up rustfmt to format my code
started using the izip!() macro to replace the repeated zip(), which improves readability especially
when rustfmt now formats my code the way it wants
starting to figure out how to add multi-hop coinswaps to the taker
in principle the maker's code doesnt need to be edited at all for this
merged a few PRs that people opened on the github
continued to write code for multi-hop coinswaps, got up to the part where the taker
broadcasts their own funding tx, then obtains signatures from maker2 to pass onto maker1
and then waits for confirmation of maker1's funding txes
wrote the sending of the ProofOfFunding message to maker2
= week-2020-12-7 =
the bug i stopped at last week was due to the wallet attempting to spend a coin on a 2of2 multisig
i hadnt implemented that yet, now is a good time so since theres many 2of2 multisig coins building
up in the regtest wallet
implemented spending from 2of2 multisig UTXOs which are completed coinswaps
made the first testnet multi-tx coinswap with random amounts(!)
posted about it on reddit, twitter and mastadon
now working on implementing multi-hop coinswaps
for that the taker will need to connect to multiple makers at once, so i had to spend
a little bit of time figuring out how to use tokio async to do that
also spent time figuring out how to use tcp timeouts with tokio async
which will be required, for example if the taker connects to a maker they need a timeout to recover
from the case where the maker is just unresponsive
figured it out
found and reported a bug in the rust compiler
coded function which connects to multiple makers at once and downloads their offers
quite a few people contacted me about working on coinswap so i think its time to release some code
even if its nowhere near finished
currently writing the README and setting up an IRC channel
= week-2020-11-30 =
continuing to code multi-tx coinswap
after a couple of days, the code for multi-tx is done, and it compiles
now to actually run it on regtest to iron out any bugs there
fixed a bug involving forgetting to unpack a vector of multisig public keys
spent a day or two on another bug which turned out to be nothing to do with my code i think
it was some weirdness where bitcoin core regtest had in its UTXO set that a certain coin had already been spent
but the wallet and `listunspent` still had the coin as unspent, so when it tried to spend it an error happened
pretty weird
i did `rescanblockchain` and it was all fixed
created the first ever multi-tx coinswap on regtest(!)
right now it uses fixed values of the individual coinswaps, ill make it use randomness as
a simple implementation and then do it on testnet
finished writing code which creates random bitcoin amounts to send in the funding transactions
although random, the amounts add up to the total amount that the user wanted to send
its a simple algorithm and theres a lot of scope for improving the building of the multiple
funding transactions, but now for its good
run into a bug, something in the wallet about obtaining UTXOs to spend
= week-2020-11-23 =
working on initial sync of core wallet including coinswap addresses, not just the xpubs
taking me longer than i thought, rust's borrow checker is slowing me down
figured out the borrow checker thing
finished the job of adding sync'ing of coinswap addresses
i wanted to create a coinswap on testnet, but i found a bug where an invalid signature is created, doh
annoyingly the bug doesnt seem to be there on regtest
tracked down the bug to a rounding error, the value 1.24997104 btc was converted to 124997103 satoshi
created the first coinswap on testnet by this project
these transactions dont look very special (which is the point) but they are coinswaps
taker pays 0.05 tbtc to the multisig address
maker pays 0.0499 to another multisig
they follow the coinswap protocol, finally handing over the private keys to each other
even though these coins are unspent (for now), they have shifted possession, the taker really does own
the UTXO worth 0.499 tbtc, and the maker really does own the UTXO worth 0.5 tbtc
(the difference of 0.001 tbtc is the fee paid by the taker to the maker)
the two UTXOs are unconnected on the blockchain
this is not a big first, because waxwing's coinswap experiment from 2017 also created coinswaps on testnet
now to code multi-tx coinswaps
essentially involves replacing a lot of items with vectors of those items
= week-2020-11-16 =
now the basic coinswap code is written im actually trying it out on regtest to get it to actually produce coinswaps
fixed a couple of simple bugs as i go through the coinswap protocol
found a bug in the wallet sync code, have to figure out how to fix it
still trying to reproduce it in a seperate file
found the bug and a workaround
found another bug in my code where for some reason the verifying of a signature fails
found the cause of the above bug, the incoming and outgoing txes were swapped around for some reason
its not swapped around, something more complicated has gone wrong
it looks like the multisig redeemscripts are wrong
found the bug finally, the cause was accidently using the maker's own public key when it shouldve been the taker's
managed to run the code from start to end
i.e. created a coinswap on regtest(!)
edited wallet code to sync and display UTXOs which came from a coinswap for which we have both privkeys
= week-2020-11-9 =
working on handling the signatures which the maker receives from the taker
that requires moving around a bunch of code so that the signatures can be correctly stored in the wallet
fundamentally this is happening because the maker code needs to store information about
the funding tx, contract tx, redeemscripts, etc until the taker replies with a message containing the signatures
finished all the moving code around, and finished the part where maker applies received signatures and
broadcasts his funding tx
finished coding the receiver contract signature message, and all the required infrastructure cod around it
now all thats left is the handover of hash preimages and privkeys
finished handover over preimages and privkeys
now to actually try out all this, up til now ive only been checking it with the rust compiler
also need to add loads of println!() to track whats going on
= week-2020-11-2 =
added the `1 OP_CSV OP_DROP` condition to the contract script to avoid transaction pinning
finished the proof-of-funding message verification, now coding the messages where the maker
requests that his contract transaction is signed
i.e. the reply to the proof-of-funding message
realized that one round trip can be eliminated from the protocol, so i created the plan for that
it works because the original protocol has messages going from one maker to another, but in reality
the messages are all routed via the taker
realized about an attack against a maker im calling the multiple contract attack, which is:
the full description is in my notes, but it requires implementing a cache of (prevout, contract-scriptpubkey)
did that
finished coding the reply to the proof-of-funding message, which is called send-sender-and-receiver-contract-txes
= week-2020-10-26 =
modifying the contract redeemscript i was planning to use, to fix the oversized preimage attack
and testing the solution a little bit
wrote code which sends a sender's contract to the other side, check it and sign it, and sends back the signature
while working on the code to allow sync'ing multiple wallets, i found
this bug in rust-bitcoin
working on the proof-of-funding message, which is a message sent when a funding transaction has confirmed
and therefore proves to the other party that the whole exchange of messages isnt a DOS
= week-2020-10-19 =
added print statements to bitcoin core, and used them to confirm that the sighashes of
the two transactions (one which works, one which doesnt work) are the same
i fed the sighash printed by bitcoincore into my rust code, then the resulting signature
was correct. so that means the problem lies somewhere in the part which calculates a sighash from
the transaction
found the issue, turns out i passed the wrong script to the sighash function, i should have passed
script_code but instead passed hash(script_code) [also called script pub key]
finished the function which creates a funding transaction
including automatically obtaining the next change address
wrote code which creates sender contract transactions (e.g. Alice-Bob/Alice contract tx)
also creating coinswap addresses (2of2 multisig) using the EC tweak scheme, and saving
these to the wallet file
started modifying wallet code so that the same full node can handle multiple instances
for example multiple makers and one taker, which is needed for testing
= week-2020-10-12 =
continuing to write the networking and protocol code
fighting with rust's borrow checker a little bit, i slightly rewrote parts of
the earlier wallet code in order to remove some lifetime compile errors
in order to continue writing the networking code, i now need to write code which generates and
checks the on-chain transactions, so that the maker and taker can sign and verify when they
receive network messages
having trouble with the rust-bitcoin dependencies
theres errors that appear when both rust-wallet and rust-bitcoin are included as dependencies
posted an issue here, maybe ill get some help
i think right now the most productive way forward is to temporarily remove rust-wallet from my codebase
its only used for mnemonic seed phrases, that can be replaced by having the user store a xprv key
this project will be testnet and regtest only for quite a long time, so theres plenty of time to
figure out the problem or wait for rust-wallet to update, and then put back seed phrases
until then theres plenty of work to be done in coding up the coinswap protocol, and that doesnt
need seed phrases
actually a possibly better solution, the dependency trouble comes when mixing types across
the two crates, i could just not do that
for example when having a ExtendedPubKey from rust-wallet, convert it to string then convert
that to an ExtendedPubKey from rust-bitcoin
theres a problem with the Bitcoin::Network enum but perhaps theres a workaround
figured out later that its pretty easy to workaround
managed to do the above, so all the types from rust-wallet are completely seperate from rust-bitcoin
appeared on a bitcoin magazine streamed conversation
working on creating and signing a transaction, which i previously wouldve used rust-wallet for
but now will figure it out just with rust-bitcoin
having some trouble with it, managed to successfully sign exactly the same transaction with rust-wallet
so now im just carefully printing going through the tx byte-by-byte figuring out why the other code fails
tried to use a debugger to step into the library and figure how whats different, but couldnt get it to work
= week-2020-10-5 =
created the boilerplate code for maker and taker networking with tokio
am able to add new network messages now fairly easily
the code requests and serves up coinswap offers
because it uses async with tokio then the server is automatically able to handle multiple clients
using serde enum representations for the messages:
this really helps because we can use the compiler for extra type checking and readability
= week-2020-9-28 =
spent most of the time recovering from my operation, but still did some work when i was able to
finished first draft of fixes to protocol design
published to mailing list
its very useful to carefully think about all the protocol steps like this, because
then edge-cases and attacks can be more easily found
now coding the networking code for the final coinswap app
= week-2020-9-21 =
helped someone who messaged me twitter debug their electrum personal server installation
wrote a full design for a two-party coinswap which contains all those fixes, most notably collateral payments
going to the hospital for an operation, so most likely wont work for the rest of the week
= week-2020-9-14 =
still coding what will eventually be the internal wallet
ran into this issue
thankfully @shesek also wrote a workaround
sadly this workaround wasnt sufficent, used a quick hack for now which ill fix later
using importmulti with bitcoincore_rpc seems to be a bit fiddly
got it to work
now have code which imports addresses and sync's a wallet, and supports seed phrase backups
now ill write a second version of the protocol design which fixes the issues found in review
of the first one
= week-2020-9-7 =
finished coding wallet generation and recovery, now coding wallet sync
had medical issues and hospital visits this week so did a bit less work
= week-2020-8-31 =
possibly made another breakthrough with fixing the vulnerability found by
ZmnSCPxj, about riskless theft attempts, it involve having the outgoing side
(e.g. alice in a simple alice-bob coinswap) be required to include her own
single-sig input to a contract transaction, then the riskless theft attempt
can be made to have an explicit cost
i'm calling it "collateral payments"
made a start on coding the actual coinswap application (finally)
started coding the part which generates and recovers a new single-sig wallet
= week 2020-8-24 =
made a short script which does the EC key tweaking from my detailed protocol design email
so that peers can agree on public keys with one fewer round trip
read this blog for a while to learn rust more
Antoine Riard found two attacks with my protocol design
- after the preimage reveal the previous hop can still broadcast a high-fee
contract tx to burn the next hop's funds
the high-fee contract tx must exist and be known to both sides in order to
make sure the contract tx gets confirmed even if mempools are congested
this can perhaps be solved using anchor outputs instead of RBF, as is already
designed for lightning
- a malicious taker can use CPFP to pin a low-fee contract tx to stop it being
RBF-bumped, and while its stuck get the other contract tx confirmed to take
its money. Once that money is taken the malicious taker can allow the first
contract tx to be confirmed and take it's money too.
this seems like it can also be solved by using just a single contract tx and
using CPFP to fee-bump instead of RBF
possibly made a breakthrough with fixing these vulnerabilities
im considering having the two peers (alice and bob, say) know slightly different
versions of the contract transactions
= week 2020-8-17 =
still working on figuring out how to use rust-bitcoin to create and spend from 2of2 multisigs
stuck a bit, might have to go through the transaction byte-by-byte
managed to get spending from a 2of2 multisig to work
now figuring out how to create and spend-from a htlc contract with rust-bitcoin
spending from with both routes (by waiting for a timeout, or by providing a hash value)
reading in detail bip112 and bip68
ZmnSCPxj replied to my mailing list email with a possible concerning problem (riskless theft
attempts) that i need to obsess over for a while. this ultimately happens because the timelock
and hashlock contract is known to both sides together
successfully made a short script which creates and spends from a htlc contract with rust-bitcoin
it is able to spend both by providing the hash preimage and by waiting for the timeout
= week 2020-8-10 =
fixed up "protocol-design-final" and sent to the mailing list
spoke on this podcast
reading code and figuring out exactly how to create and spend from a 2of2 multisig address using rust-bitcoin
= week 2020-8-3 =
continuing to work on the detailed design of the protocol
came up with an attack on my earlier design which included miner fees
where a malicious taker Alice could cause maker Bob to waste all his money on miner fees
and wrote down a defence against this attack
see the note (4/8/2020) in file "routed-coinswap-with-miner-fees"
started a document called "user warnings" to jot down things which will need to be in the user manual
e.g. you have a risk that your coins will be locked up for a little bit (same as in lightning channel unilateral close)
finished the document "multi-tx-routed-coinswap-with-branching" which has the detailed protocol design
that was a great exercise and i found a couple of edge cases
now ill work on the final protocol design which includes every feature, and then publish that for review
finished first draft of document "protocol-design-final", so now need to read it closely again and
eventually send it to the dev mailing list for review
= week 2020-7-27 =
posted my review in the taproot PR in secp256k1
still have medical problems meaning i cant work as much
working on protocol design for how takers and makers communicate, and what transactions they broadcast when
handling miner fees seems to be an issue, i must come up with a good way to handle it
designed a whole protocol for routed coinswaps which entirely handle miner fees
written in the file "routed-coinswap-with-miner-fees"
while designing this i came across a possible problem i hadnt forseen
i call it the "who goes first in routed coinswaps" problem
after a lot of thinking and writing, i came up with a solution to it which should work
the solution is based on using retaliation to make it not possible to DOS for free
= week 2020-7-20 =
used rust-bitcoin and rust-wallet to sign a transaction
worked much less this week due to medical issues
reviewing code from libsecp256k1
<gmaxwell> This is the libsecp256k1 PR for BIP340, it's
the majority of the lines of code of the taproot change. It could really use more reviewers, and was recently
squashed after lots of revisions from review.
edit: 2020/9/11 merged finally!
= week 2020-7-13 =
read the book
its still unfinished, lots of TODOs
ill play with the http server example in the book, and maybe learn more from there
studying the bwt project which uses async via tokio and async-std
tokio and async_std are both used in only
the tokio pages are useful
intend to play with this example
created small tokio demo scripts, such as:
heartbeat - prints a message at reguler intervals
two heartbeats - prints two different messages at two different regular intervals
multi heartbeats - prints N different messages are N different intervals, for arbitrary number N
decided not to figure out how to make multi_heartbeat because ill never use something like that
it requires figuring out how to make the join! macro work for a list of futures
later i found out you can do that with futures::future::join_all
created a heartbeat server - which accepts tcp connections and at regular intervals sends a message down all the client sockets
read a bit of bwt to see how it uses async, with tokio and async_std
reading the code of
which steven roose linked to me in an email exchange
skimmed that code, i think i understand it at a high level
managed to use the RPC library to obtain the best block hash from bitcoind
one snag was that i accidently used the wrong username and password, and
the error message was not descriptive enough
i decided to open an issue about it
= week 2020-7-6 =
continuing work on rust http server
learning about tests, seperate modules, using cargo to run tests
file and path handling in rust
slowly improving the server
coded a function which generates a MIME type for the http reply
implemented http keep-alive instead of closing the connection after each request
have the server creates an index page if a directory is GET requested, that page lists all the files within it
used the external crate chronos to order to format the Date Modified as a string nicely
then will move onto implementing an async version of the server
start with having two applications in the project, the second one for async
= week 2020-6-29 =
finished the rust irc bot
it features:
* connects to a network and irc channel
* keeps track of nicks in the channel along with their op powers (including voice and half-op)
* keeps track of updates to above by watching for MODE messages
* if a nick addresses the bot by name it will reply "hello", if the nick has ops it replies "hello sire"
* allows op'd users to use the command !raw which sends a raw message to the server, which can be
used for sending QUIT and testing how the bot handles the server closing the connection
* implements heartbeat by using socket timeouts, which could be used for pinging the server to keep the connection alive
i learned lots about rust; such as borrowing, lifetimes, collections, tcp sockets, string parsing
skim read some other irc bots in rust
this appears to be _the_ irc lib for rust, and it also uses asyncio which i want to learn too
read the chapter on cargo in the rust book, i skipped it last time
read the code of bwt again, i think i got more from it on this second reading
starting to code a http server
aiming to write test-driven code as i go
use the automated code formatting
aiming to first have a single-thread single-socket model, then move to asyncio
actually not asyncio, maybe do it with multiple threads and then asyncio, the async rust book is unfinished
seperate files and modules, one mod controlling the protocol parsing, so later it can be dropped into the async version
two binary files, one for single-client other for async, might work
= week 2020-6-22 =
still writing an irc bot in rust, learning a lot about string manipulation, and with rust's borrowing feature
answered some issues on the EPS github
reviewed the release notes of the next joinmarket version
still writing the irc, more things about ownership
every time i run into an issue i search the web to read more details
the &str type has functions called `to_string()` but `as_bytes()`
turns out `as_` implies conversion, `to_` implies allocation, and this is a common pattern in rust libs
still coding rust, learned a couple of things about ownership and lifetimes
fixed joinmarket issue #610 and tested waxwing's PR #611 finding a bug
= week 2020-6-15 =
still reading the rust book
finished the rust book except the cargo chapter
coded a rust script to generate a heatmap of the sin function
also calculated the value of pi using a monte carlo simulation
started writing a script to generate "worlds" of particles for the software KDE-step
ill generate a galaxy, then two galaxies colliding
this is useful to practice using iterators and structs in rust
started studying bwt, now seems like a good time to read other people's code
finished the skim reading
started writing an irc bot in rust
= week 2020-6-8 =
got a grant from the Human Rights Foundation
gave interview with Alyssa Hertig who will write an article about CoinSwap on coindesk
gave interview with Aaron van Wirdum journalist
continued reading the rust book
discussed coinswap and payjoin on the bitcoin dev mailing list
and taint analysis
reviewed the python-bitcointx pull request on joinmarket
set up a date for a podcast recording on the whatbitcoindid podcast
= week 2020-6-1 =
still learning rust
did the exercises in the rust book about collections (calculating averages)
merged the fidelity bond wallets PR
discussed on the bitcoin dev mailing list
went on the Tales From The Crypt podcast
released electrum personal server 0.2.1
= week 2020-5 25=
published coinswap design document to the mailing list, and github gist
started working on `announce-fidelity-bonds` branch which edits the joinmarket makers and takers to create and parse fidelity bonds announcements
it assumes the fidelity bond wallet branch is merged, which iv been waiting to get tested/reviewed enough to merge
started learning rust, working through the rust book

This comment has been minimized.

Copy link

@themighty1 themighty1 commented Oct 28, 2020

Nice work, Chris, thanks for keeping this. It is inspiring to read.


This comment has been minimized.

Copy link

@ta32 ta32 commented Dec 5, 2020

if you do some work on rust either learning or creating a prototype could you consider streaming it on twitch? Would be interesting to watch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.