To support the development of our DID method, we created two
command-line applications. The first application, txid2txref
, can
convert Bitcoin transaction ids, or
txids, to
txrefs,
and vice-versa. It uses bitcoind to verify the transactions. The second
application, createBtcrDid
, will create a decentralized identifier
(DID) on the Bitcoin
blockchain. It also uses bitcoind to submit the transaction needed to
create the DID.
This README assumes that you have bitcoind running somewhere, locally or remotely. bitcoind needs to be a full node and needs to have a full transaction database (launched with -txindex or with txindex=1 in bitcoin.conf) and needs to have RPC turned on (launched with -server or server=1 in bitcoin.conf).
We have developed and tested txid2txref
and createBtcrDid
on Debian,
Ubuntu and MacOS systems. Each OS has it differences, so please check
the instructions below:
The following instructions should work with any of Debian 8, 9, 10, or 11 and Ubuntu 16, 18 and 20. Intermediate and subsequent versions will probably work as well, but if you have any problems please let us know.
You will need to have a basic C++ development setup and several dependent packages:
$ sudo apt-get update
$ sudo apt-get install make cmake gcc g++ git unzip libcurl4-openssl-dev libjsoncpp-dev uuid-dev libjsonrpccpp-dev libjsonrpccpp-tools libboost-dev
Clone libbitcoin-api-cpp from Github.
$ git clone https://github.com/minium/bitcoin-api-cpp.git
This is a cmake-based project, so the standard process can be done here:
cd bitcoin-api-cpp
mkdir build
cd build
cmake ..
make
sudo make install
If you don't already have it, clone btcr-DID-method from Github. There are git submodules in the project, so we need to be sure to init and update them correctly:
$ git clone --recurse-submodules https://github.com/dcdpr/btcr-DID-method.git
This is a cmake-based project, so the standard process can be done here:
cd btcr-DID-method
mkdir build
cd build
cmake ..
make
The following instructions should work with any of MacOS 10.13: "High Sierra", 10.14: "Mojave" and 10.15: "Catalina". Subsequent versions will probably work as well, but if you have any problems please let us know.
You will want to install homebrew if you haven't already. See their installation instructions, or try:
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Next, you will need to get some packages:
$ brew update
$ brew install jsoncpp libjson-rpc-cpp boost
homebrew installs jsoncpp (from above step) a little differently than bitcoin-api-cpp expects. Until the bitcoin-api-cpp folks update their project, you should clone our local copy of bitcoin-api-cpp from Github.
$ git clone https://github.com/danpape/bitcoin-api-cpp.git
This is a cmake-based project, so the standard process can be done here:
cd bitcoin-api-cpp
mkdir build
cd build
cmake ..
make
sudo make install
If you don't already have it, clone btcr-DID-method from Github. There are git submodules in the project, so we need to be sure to init and update them correctly:
$ git clone --recurse-submodules https://github.com/dcdpr/btcr-DID-method.git
This is a cmake-based project, so the standard process can be done here:
cd btcr-DID-method
mkdir build
cd build
cmake ..
make
The txid2txref
application is based on the txid2bech32
app created during
the 2017 BTCR Virtual Hackathon.
txid2txref
is run as txid2txref [txid]
and when given a valid txid
,
will output a txref
along with some other info. txid2txref
will
communicate with an instance of bitcoind via RPC to retrieve information
about that transaction so it can create the txref
. txid2txref
can also
be run as txid2txref [txref]
and will output info about the bitcoin
transaction referred to.
You can ask txid2txref
for help and it will show all the runtime options
available:
$ ./src/txid2txref --help
Usage: txid2txref [options] <txid|txref>
-h --help Print this help
--rpcconnect [host or IP] RPC host (default: 127.0.0.1)
--rpcuser [user] RPC user
--rpcpassword [pass] RPC password
--rpcport [port] RPC port (default: try both 8332 and 18332)
--config [config_path] Full pathname to bitcoin.conf (default: <homedir>/.bitcoin/bitcoin.conf)
--txoIndex [index #] Index # for TXO within the transaction (default: 0)
<txid|txref> input: can be a txid to encode, or a txref to decode
Many of the runtime options for txid2txref
are for connecting to
bitcoind over RPC. There are four --rpc*
options that you can use for
connecting to a local or remote bitcoind:
$ ./src/txid2txref --rpcuser bitcoinrpc --rpcpassword super-secret-passwd --rpcconnect 127.0.0.1 --rpcport 18332 <txid>
{...}
If you have bitcoind running locally, you probably have a bitcoin.conf
file with all the RPC info in there. If so, you can use it instead of
setting all of the --rpc*
options:
$ # by default it will look in <homedir>/.bitcoin/bitcoin.conf
$ ./src/txid2txref <txid>
{...}
$ # or you can use a different location
$ ./src/txid2txref --config /tmp/bitcoin.conf <txid>
{...}
When given a txid, txid2txref
will connect to bitcoind to verify it is a
valid txid and, if found, gather some info about it. Then it will output
some JSON with details about that transaction, and the txref.
$ ./src/txid2txref f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7521234
Error: transaction f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7521234 not found.
$ ./src/txid2txref f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7528107
{
"txid": "f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7528107",
"txref": "txtest1:xyv2-xzpq-q63z-7p4",
"did": "did:btcr:xyv2-xzpq-q63z-7p4",
"network": "test",
"block-height": "1152194",
"transaction-index": "1",
"txo-index": "0",
"query-string": "f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7528107"
}
txid2txref
can also output an extended txref if the --txoIndex flag is given.
$ ./src/txid2txref f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7528107 | jq '{txref}'
{
"txref": "txtest1:xyv2-xzpq-q63z-7p4"
}
$ ./src/txid2txref --txoIndex 1 f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7528107 | jq '{txref}'
{
"txref": "txtest1:8yv2-xzpq-qpqq-cew3-4s"
}
Alternately, instead of a txid, txid2txref
can be given a txref to
decode and look up the transaction info in bitcoind:
$ ./src/txid2txref txtest1:8yv2-xzpq-qpqq-cew3-4s
{
"txid": "f8cdaff3ebd9e862ed5885f8975489090595abe1470397f79780ead1c7528107",
"txref": "txtest1:8yv2-xzpq-qpqq-cew3-4s",
"did": "did:btcr:8yv2-xzpq-qpqq-cew3-4s",
"network": "test",
"block-height": "1152194",
"transaction-index": "1",
"txo-index": "1",
"query-string": "txtest1:8yv2-xzpq-qpqq-cew3-4s"
}
You can ask createBtcrDid
for help, and it will show all the runtime
options available:
> ./src/createBtcrDid --help
Usage: createBtcrDid [options] <inputXXX> <outputAddress> <private key> <fee> <ddoRef>
-h --help Print this help
--rpcconnect [host or IP] RPC host (default: 127.0.0.1)
--rpcuser [user] RPC user
--rpcpassword [pass] RPC password
--rpcport [port] RPC port (default: try both 8332 and 18332)
--config [config_path] Full pathname to bitcoin.conf (default: <homedir>/.bitcoin/bitcoin.conf)
--txoIndex [index] Index # of which TXO to use from the input transaction (default: 0)
-n --dryrun Do everything except submit transaction to blockchain
<inputXXX> input: (bitcoin address, txid, txref) needs at least slightly more unspent BTCs than your offered fee
<outputAddress> output bitcoin address: will receive transaction change and be the basis for your DID
<private key> private key in base58 (wallet import format)
<fee> fee you are willing to pay (suggestion: >0.001 BTC)
<ddoRef> reference to a DDO you want as part of your DID (optional)
Many of the runtime options for createBtcrDid
are for connecting to
bitcoind over RPC. There are four --rpc*
options that you can use for
connecting to a local or remote bitcoind:
$ ./src/createBtcrDid --rpcuser bitcoinrpc --rpcpassword super-secret-passwd --rpcconnect 127.0.0.1 --rpcport 18332 ...
If you have bitcoind running locally, you probably have a bitcoin.conf
file with all the RPC info in there. If so, you can use it instead of
setting all of the --rpc*
options:
$ # by default it will look in <homedir>/.bitcoin/bitcoin.conf
$ ./src/createBtcrDid ...
{...}
$ # or you can use a different location
$ ./src/createBtcrDid --config /tmp/bitcoin.conf ...
{...}
createBtcrDid
has many required positional parameters:
This is the input transaction--where you need to have at least slightly
more unspent BTCs than your offered fee (see below). You can refer to
this transaction in many ways: a Bitcoin address (with optional
txoIndex, given with --txoIndex
parameter); a txid (with optional
txoIndex); a txref (with optional txoIndex).
This is the output Bitcoin address. It will receive transaction change and be the basis for your DID.
private key in base58 (wallet import format)
fee you are willing to pay (suggestion: >0.001 BTC)
reference to a DDO you want as part of your DID. Usually a URL to a JSON-LD document. (optional)
Some prerequisites:
- you need a running instance of bitcoind, with the option "txindex=1" enabled so you have full transaction history.
- you need to have some BTC, either on the mainnet, testnet, or restest blockchain (whatever your bitcoind is running)
- you need the txid of a transaction with your BTC, and the index of the TXO you want to use (if it is other than 0)
- if you want your DID to have a reference to an external document with more info (a DDO) then make sure you have a URL for where it can be retrieved from.
Make sure you know the txid and how much you have to spend from it. You can use bitcoin-cli to check:
$ bitcoin-cli listunspent | jq -r '.[] | { txid: .txid, address: .address, vout: .vout, amount: .amount }'
{
"txid": "79d864cc59b0c3ac240fc78e5a79edb13182b88c9ed1c60526eda6657a5d5e9e",
"address": "mvwGweRzRDwydpJfW1uqWJN4iZvNBZ9zZ4",
"vout": 0,
"amount": 0.02
}
If you want to start using txrefs right away, you can use txid2txref
to
convert your txid:
$ ./src/txid2txref --txoIndex 0 79d864cc59b0c3ac240fc78e5a79edb13182b88c9ed1c60526eda6657a5d5e9e | jq '{txref}'
{
"txref": "txtest1:xvn9-0z8q-qn3s-nf7"
}
You need to decide how much you want to spend to create your DID--this is the transaction fee. You probably want this as low as possible. For the testnet, you can probably get by with a fee of 0.0005 BTC.
You need a new address for your transaction change to go to. This will also be the basis for your DID. You can make one with bitcoin-cli:
$ bitcoin-cli getrawchangeaddress
myxJdFGMAnX4SiBg2hTKsZRr8ReE5irjS5
Finally, you need the private key for the address of your original transaction. You can get it from bitcoin-cli:
$ bitcoin-cli dumpprivkey mvwGweRzRDwydpJfW1uqWJN4iZvNBZ9zZ4
randomrandomrandomrandomrandomrandomrandomrandomrand
Putting this all together, now you are ready to run createBtcrDid
:
$ ./src/createBtcrDid \
79d864cc59b0c3ac240fc78e5a79edb13182b88c9ed1c60526eda6657a5d5e9e \
myxJdFGMAnX4SiBg2hTKsZRr8ReE5irjS5 \
randomrandomrandomrandomrandomrandomrandomrandomrand \
0.0005 \
https://raw.githubusercontent.com/danpape/self/master/ddo-ext.jsonld
Transaction submitted. Result txid: cd94e5a4a1aa1b19988faed93d31d50195b75390130304358369a63e8caec5ef
Using a block explorer, you can check that it looks good. For instance,
you can look up this example transaction on
blockcypher.com
and can see that 0.0005 BTC was spent, from
mvwGweRzRDwydpJfW1uqWJN4iZvNBZ9zZ4
to
myxJdFGMAnX4SiBg2hTKsZRr8ReE5irjS5
. There is also an extra TXO there,
with 0.0 BTC which contains the DDO linked from github.
Finally, you can again use txid2txref
to get your DID:
$ ./src/txid2txref --txoIndex 1 cd94e5a4a1aa1b19988faed93d31d50195b75390130304358369a63e8caec5ef | jq '{did}'
{
"did": "did:btcr:8km9-0zyz-qpqq-sutc-5x"
}
In Decemeber, 2019, Pieter Wuille did research into the error detecting
properties of the bech32 encoding alorithm. Based on a problem and fix he found, an internal constant in the algorithm has been updated from 1
to 0x3FFFFFFF
. This
has the effect of changing the checksum values embedded in the txrefs and DIDs output by our programs.
More info can be found here.
If you find that a DID is reported as invalid by BTCR, you may be using an old one with a (now) invalid checksum. In that case, you should update the txref part of your DID with the txid2tref
program. There are no known outdated implementations.