use fencing for code blocks

The MMGen Project 2023-01-25 21:18:49 +00:00
commit 2e37167340
Signed by: mmgen
GPG key ID: 3F8B1861E32B7DA2
17 changed files with 1272 additions and 793 deletions

@ -33,7 +33,9 @@ In addition, ERC20 token creation and deployment are supported via the
From the MMGen repository root, type:
$ python3 -m pip install --no-deps --user -r eth-requirements.txt
```text
$ python3 -m pip install --no-deps --user -r eth-requirements.txt
```
#### <a id="a_oe">Install and run Geth, Parity or OpenEthereum</a>
@ -48,7 +50,9 @@ needn’t install them on your offline machine.
For Geth, the following command-line options are required:
--http --http.api=eth,web3,txpool --http.port=8745
```text
--http --http.api=eth,web3,txpool --http.port=8745
```
Geth and OE have dropped support for Ethereum Classic, but MMGen supports
transacting ETC via the legacy [Parity][pd] daemon. Invoke Parity with
@ -58,7 +62,9 @@ same as for OpenEthereum.
If you’re running OE or Parity on a different machine from MMGen, add the
following options to the daemon command line:
--jsonrpc-hosts=all --jsonrpc-interface=<daemon IP address>
```text
--jsonrpc-hosts=all --jsonrpc-interface=<daemon IP address>
```
To run OE or Parity offline, use `--mode=offline`, otherwise `--mode=active`.
@ -96,11 +102,15 @@ must be replaced with real ones.*
Generate some ETH addresses with your default wallet:
$ mmgen-addrgen --coin=eth 1-5
```text
$ mmgen-addrgen --coin=eth 1-5
```
Create an EOS token tracking wallet and import the addresses into it:
$ mmgen-addrimport --coin=eth --token-addr=86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0 ABCDABCD-ETH[1-5].addrs
```text
$ mmgen-addrimport --coin=eth --token-addr=86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0 ABCDABCD-ETH[1-5].addrs
```
*Unlike the case with BTC and derivatives, ETH and ETC tracking wallets are
created and managed by MMGen itself and located under the MMGen data directory.
@ -112,21 +122,29 @@ Now send 10+ EOS from an exchange or another wallet to address `ABCDABCD:E:1`.
Then create a TX sending 10 EOS to third-party address `aabbccdd...`, with
change to `ABCDABCD:E:2`:
$ mmgen-txcreate --coin=eth --token=eos aabbccddaabbccddaabbccddaabbccddaabbccdd,10 ABCDABCD:E:2
```text
$ mmgen-txcreate --coin=eth --token=eos aabbccddaabbccddaabbccddaabbccddaabbccdd,10 ABCDABCD:E:2
```
On your offline machine, sign the TX:
$ mmgen-txsign --coin=eth --token=eos ABC123-EOS[10,50000].rawtx
```text
$ mmgen-txsign --coin=eth --token=eos ABC123-EOS[10,50000].rawtx
```
*You can also set up and use [autosigning][X] on the offline machine.*
On your online machine, send the TX:
$ mmgen-txsend --coin=eth --token=eos ABC123-EOS[10,50000].sigtx
```text
$ mmgen-txsend --coin=eth --token=eos ABC123-EOS[10,50000].sigtx
```
View your EOS tracking wallet:
$ mmgen-tool --coin=eth --token=eos twview
```text
$ mmgen-tool --coin=eth --token=eos twview
```
To transact ETH instead of EOS, omit the `--token` and `--token-addr` arguments.
@ -141,15 +159,17 @@ correct version is to compile it from source.
Clone the repository and build:
$ git clone --recursive https://github.com/ethereum/solidity.git
$ cd solidity
$ git checkout v0.8.7
$ ./scripts/install_deps.sh
$ mkdir build
$ cd build
$ cmake -DUSE_CVC4=OFF -DUSE_Z3=OFF ..
$ make -j4 solc
$ sudo install -v --strip solc/solc /usr/local/bin
```text
$ git clone --recursive https://github.com/ethereum/solidity.git
$ cd solidity
$ git checkout v0.8.7
$ ./scripts/install_deps.sh
$ mkdir build
$ cd build
$ cmake -DUSE_CVC4=OFF -DUSE_Z3=OFF ..
$ make -j4 solc
$ sudo install -v --strip solc/solc /usr/local/bin
```
##### Create and deploy a token
@ -158,16 +178,20 @@ must replace them with real ones.*
Create a token 'MFT' with default parameters, owned by `ddeeff...` (`ABCDABCD:E:1`):
# Do this in the MMGen repository root:
$ scripts/create-token.py --coin=ETH --symbol=MFT --name='My First Token' ddEEFFDdEEFfddEeffDDEefFdDeeFFDDEeFFddEe
```text
# Do this in the MMGen repository root:
$ scripts/create-token.py --coin=ETH --symbol=MFT --name='My First Token' ddEEFFDdEEFfddEeffDDEefFdDeeFFDDEeFFddEe
```
Deploy the token on the ETH blockchain:
$ mmgen-txdo --coin=eth --tx-gas=200000 --contract-data=SafeMath.bin
$ mmgen-txdo --coin=eth --tx-gas=250000 --contract-data=Owned.bin
$ mmgen-txdo --coin=eth --tx-gas=1100000 --contract-data=Token.bin
...
Token address: abcd1234abcd1234abcd1234abcd1234abcd1234
```text
$ mmgen-txdo --coin=eth --tx-gas=200000 --contract-data=SafeMath.bin
$ mmgen-txdo --coin=eth --tx-gas=250000 --contract-data=Owned.bin
$ mmgen-txdo --coin=eth --tx-gas=1100000 --contract-data=Token.bin
...
Token address: abcd1234abcd1234abcd1234abcd1234abcd1234
```
*These Gas amounts seem to work for these three contracts, but feel free to
experiment. Make sure you understand the difference between Gas amount and Gas
@ -175,11 +199,15 @@ price!*
Create an MFT token tracking wallet and import your ETH addresses into it:
$ mmgen-addrimport --coin=eth --token-addr=abcd1234abcd1234abcd1234abcd1234abcd1234 ABCDABCD-ETH[1-5].addrs
```text
$ mmgen-addrimport --coin=eth --token-addr=abcd1234abcd1234abcd1234abcd1234abcd1234 ABCDABCD-ETH[1-5].addrs
```
View your MFT tracking wallet:
$ mmgen-tool --coin=eth --token=mft twview
```text
$ mmgen-tool --coin=eth --token=mft twview
```
Other token parameters can be customized too. Type `scripts/create-token.py --help`
for details.
@ -215,7 +243,9 @@ private data on your online machine.*
To generate five Monero key/address pairs from your default wallet, invoke the
following, making sure to answer ‘y’ at the Encrypt prompt:
$ mmgen-keygen --coin=xmr 1-5
```text
$ mmgen-keygen --coin=xmr 1-5
```
In addition to spend and view keys, the resulting key/address file also
includes a wallet password for each address (the double SHA256 hash of the
@ -224,19 +254,25 @@ spend key, truncated to 16 bytes).
Now create a Monero wallet for each address in the file by invoking the
following command:
$ mmgen-xmrwallet create *XMR*.akeys.mmenc
```text
$ mmgen-xmrwallet create *XMR*.akeys.mmenc
```
Each wallet will be uniquely named using the address index and encrypted with
the address’ unique wallet password. No user interaction is required during
the creation process. By default, wallets are synced to the current block
height, as they’re assumed to be empty, but this behavior can be overridden:
$ mmgen-xmrwallet --restore-height=123456 create *XMR*.akeys.mmenc
```text
$ mmgen-xmrwallet --restore-height=123456 create *XMR*.akeys.mmenc
```
To keep your wallets in sync as the Monero blockchain grows, use the `sync`
subcommand:
$ mmgen-xmrwallet sync *XMR*.akeys.mmenc
```text
$ mmgen-xmrwallet sync *XMR*.akeys.mmenc
```
No user interaction is required here either, which is very helpful when you
have multiple wallets requiring long sync times.
@ -250,7 +286,9 @@ MMGen’s enhanced support for Zcash includes generation of **z-addresses.**
Generate ten Zcash z-address key/address pairs from your default wallet:
$ mmgen-keygen --coin=zec --type=zcash_z 1-10
```text
$ mmgen-keygen --coin=zec --type=zcash_z 1-10
```
The addresses’ view keys are included in the output file as well.
@ -261,39 +299,50 @@ non-standard Scrypt hash preset, take care to remember it.
To generate Zcash t-addresses, just omit the `--type` argument:
$ mmgen-keygen --coin=zec 1-10
```text
$ mmgen-keygen --coin=zec 1-10
```
### <a id="a_kg">Key/address generation for 144 Bitcoin-derived altcoins</a>
To generate key/address pairs for these coins, just specify the coin’s symbol
with the `--coin` argument:
# For DASH:
$ mmgen-keygen --coin=dash 1-10
# For Emercoin:
$ mmgen-keygen --coin=emc 1-10
```text
# For DASH:
$ mmgen-keygen --coin=dash 1-10
# For Emercoin:
$ mmgen-keygen --coin=emc 1-10
```
For compressed public keys, add the `--type=compressed` option:
$ mmgen-keygen --coin=dash --type=compressed 1-10
```text
$ mmgen-keygen --coin=dash --type=compressed 1-10
```
If it’s just the addresses you want, then use `mmgen-addrgen` instead:
$ mmgen-addrgen --coin=dash --type=compressed 1-10
```text
$ mmgen-addrgen --coin=dash --type=compressed 1-10
```
Regarding encryption of key/address files, see the note for Zcash above.
Here’s a complete list of supported altcoins as of this writing:
2give,42,611,ac,acoin,alf,anc,apex,arco,arg,aur,bcf,blk,bmc,bqc,bsty,btcd,
btq,bucks,cann,cash,cat,cbx,ccn,cdn,chc,clam,con,cpc,crps,csh,dash,dcr,dfc,
dgb,dgc,doge,doged,dope,dvc,efl,emc,emd,enrg,esp,fai,fc2,fibre,fjc,flo,flt,
fst,ftc,gcr,good,grc,gun,ham,html5,hyp,icash,infx,inpay,ipc,jbs,judge,lana,
lat,ldoge,lmc,ltc,mars,mcar,mec,mint,mobi,mona,moon,mrs,mue,mxt,myr,myriad,
mzc,neos,neva,nka,nlg,nmc,nto,nvc,ok,omc,omni,onion,onx,part,pink,pivx,pkb,
pnd,pot,ppc,ptc,pxc,qrk,rain,rbt,rby,rdd,ric,sdc,sib,smly,song,spr,start,
sys,taj,tit,tpc,trc,ttc,tx,uno,via,vpn,vtc,wash,wdc,wisc,wkc,wsx,xcn,xgb,
xmg,xpm,xpoke,xred,xst,xvc,zet,zlq,zoom,zrc,bch,etc,eth,ltc,xmr,zec
```text
2give,42,611,ac,acoin,alf,anc,apex,arco,arg,aur,bcf,blk,bmc,bqc,bsty,btcd,
btq,bucks,cann,cash,cat,cbx,ccn,cdn,chc,clam,con,cpc,crps,csh,dash,dcr,dfc,
dgb,dgc,doge,doged,dope,dvc,efl,emc,emd,enrg,esp,fai,fc2,fibre,fjc,flo,flt,
fst,ftc,gcr,good,grc,gun,ham,html5,hyp,icash,infx,inpay,ipc,jbs,judge,lana,
lat,ldoge,lmc,ltc,mars,mcar,mec,mint,mobi,mona,moon,mrs,mue,mxt,myr,myriad,
mzc,neos,neva,nka,nlg,nmc,nto,nvc,ok,omc,omni,onion,onx,part,pink,pivx,pkb,
pnd,pot,ppc,ptc,pxc,qrk,rain,rbt,rby,rdd,ric,sdc,sib,smly,song,spr,start,
sys,taj,tit,tpc,trc,ttc,tx,uno,via,vpn,vtc,wash,wdc,wisc,wkc,wsx,xcn,xgb,
xmg,xpm,xpoke,xred,xst,xvc,zet,zlq,zoom,zrc,bch,etc,eth,ltc,xmr,zec
```
Note that support for most of these coins is EXPERIMENTAL. Many of them have
received only minimal testing, or no testing at all. At startup you’ll be

@ -74,10 +74,12 @@ options on the command line.
Sample MMGen command invocations:
$ mmgen-txcreate --help
$ mmgen-addrgen --verbose 1-10
$ mmgen-walletgen
$ mmgen-walletgen --quiet --seed-len 128
```text
$ mmgen-txcreate --help
$ mmgen-addrgen --verbose 1-10
$ mmgen-walletgen
$ mmgen-walletgen --quiet --seed-len 128
```
#### <a id="a_cf">Configuration file</a>
@ -126,9 +128,11 @@ source in all commands where a seed source is required.*
On your offline computer, generate an MMGen wallet:
$ mmgen-walletgen
...
MMGen wallet written to file '/home/username/.mmgen/89ABCDEF-76543210[256,3].mmdat'
```text
$ mmgen-walletgen
...
MMGen wallet written to file '/home/username/.mmgen/89ABCDEF-76543210[256,3].mmdat'
```
`89ABCDEF` is the Seed ID; `76543210` is the Key ID. These are randomly
generated, so your IDs will of course be different than these.
@ -162,23 +166,25 @@ backups** can’t be overestimated.
Now generate ten Segwit-P2SH addresses with your just-created wallet:
$ mmgen-addrgen --type=segwit 1-10
...
Addresses written to file '89ABCDEF-S[1-10].addrs'
```text
$ mmgen-addrgen --type=segwit 1-10
...
Addresses written to file '89ABCDEF-S[1-10].addrs'
$ cat '89ABCDEF-S[1-10].addrs'
89ABCDEF SEGWIT {
1 36bNmyYISiptuvJG3X7MPwiiS4HYvD7ksE
2 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc
3 3HgYCsfqYzIg7LVVfDTp7gYJocJEiDAy6N
4 34Tu3z1tiexXDonNsFIkvzqutE5E3pTK8s
5 3PeI55vtp2bX2uKDkAAR2c6ekHNYe4Hcq7
6 3FEqfEsSILwXPfMvVvVuUovzTaaST62Mnf
7 3LTTzuhMqPLwQ4IGCwwugny6ZMtUQJSJ1
8 3F9495H8EJLb54wirgZkVgI47SP7M2RQWv
9 3JbrCyt7BdxRE9GX1N7GiEct8UnIjPmpYd
10 3H7vVTk4ejUbQXw45I6g5qvPBSe9bsjDqh
}
$ cat '89ABCDEF-S[1-10].addrs'
89ABCDEF SEGWIT {
1 36bNmyYISiptuvJG3X7MPwiiS4HYvD7ksE
2 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc
3 3HgYCsfqYzIg7LVVfDTp7gYJocJEiDAy6N
4 34Tu3z1tiexXDonNsFIkvzqutE5E3pTK8s
5 3PeI55vtp2bX2uKDkAAR2c6ekHNYe4Hcq7
6 3FEqfEsSILwXPfMvVvVuUovzTaaST62Mnf
7 3LTTzuhMqPLwQ4IGCwwugny6ZMtUQJSJ1
8 3F9495H8EJLb54wirgZkVgI47SP7M2RQWv
9 3JbrCyt7BdxRE9GX1N7GiEct8UnIjPmpYd
10 3H7vVTk4ejUbQXw45I6g5qvPBSe9bsjDqh
}
```
Note that the address range `1-10` specified on the command line is included in
the resulting filename.
@ -199,29 +205,38 @@ Segwit support, compressed (`C`) addresses are the best choice.
Generation examples for various address types:
# legacy (uncompressed P2PKH)
$ mmgen-addrgen 1-10
...
$ cat '89ABCDEF[1-10].addrs'
89ABCDEF {
1 12GiSWo9zIQgkCmjAaLIrbPwXhKry2jHhj
...
```text
# legacy (uncompressed P2PKH)
$ mmgen-addrgen 1-10
...
# compressed P2PKH
$ mmgen-addrgen --type=compressed 1-10
...
$ cat '89ABCDEF-C[1-10].addrs'
89ABCDEF COMPRESSED {
1 13jbRxWjswXtaDzLBJDboMcIe6nLohFb9M
...
$ cat '89ABCDEF[1-10].addrs'
89ABCDEF {
1 12GiSWo9zIQgkCmjAaLIrbPwXhKry2jHhj
...
```
# Bech32 (native Segwit)
$ mmgen-addrgen --type=bech32 1-10
...
$ cat '89ABCDEF-B[1-10].addrs'
89ABCDEF BECH32 {
1 bc1q9c9273thh3xh86lk6z34raejz6j2s8ytgyb7my
...
```text
# compressed P2PKH
$ mmgen-addrgen --type=compressed 1-10
...
$ cat '89ABCDEF-C[1-10].addrs'
89ABCDEF COMPRESSED {
1 13jbRxWjswXtaDzLBJDboMcIe6nLohFb9M
...
```
```text
# Bech32 (native Segwit)
$ mmgen-addrgen --type=bech32 1-10
...
$ cat '89ABCDEF-B[1-10].addrs'
89ABCDEF BECH32 {
1 bc1q9c9273thh3xh86lk6z34raejz6j2s8ytgyb7my
...
```
Note that for non-legacy address types the code letter is included in the
filename.
@ -239,27 +254,33 @@ provide the addresses with labels. We’ll use the labels ‘Donations’, ‘S
Make a copy of the address file
$ cp '89ABCDEF-S[1-10].addrs' my.addrs
```text
$ cp '89ABCDEF-S[1-10].addrs' my.addrs
```
and edit it using the text editor of your choice,
$ nano my.addrs
```text
$ nano my.addrs
```
adding labels to the addresses you’ve chosen to spend to:
# My first MMGen addresses
89ABCDEF SEGWIT {
1 36bNmyYISiptuvJG3X7MPwiiS4HYvD7ksE Donations
2 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc Storage 1
3 3HgYCsfqYzIg7LVVfDTp7gYJocJEiDAy6N Storage 2
4 34Tu3z1tiexXDonNsFIkvzqutE5E3pTK8s Storage 3
5 3PeI55vtp2bX2uKDkAAR2c6ekHNYe4Hcq7
6 3FEqfEsSILwXPfMvVvVuUovzTaaST62Mnf
7 3LTTzuhMqPLwQ4IGCwwugny6ZMtUQJSJ1
8 3F9495H8EJLb54wirgZkVgI47SP7M2RQWv
9 3JbrCyt7BdxRE9GX1N7GiEct8UnIjPmpYd
10 3H7vVTk4ejUbQXw45I6g5qvPBSe9bsjDqh
}
```text
# My first MMGen addresses
89ABCDEF SEGWIT {
1 36bNmyYISiptuvJG3X7MPwiiS4HYvD7ksE Donations
2 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc Storage 1
3 3HgYCsfqYzIg7LVVfDTp7gYJocJEiDAy6N Storage 2
4 34Tu3z1tiexXDonNsFIkvzqutE5E3pTK8s Storage 3
5 3PeI55vtp2bX2uKDkAAR2c6ekHNYe4Hcq7
6 3FEqfEsSILwXPfMvVvVuUovzTaaST62Mnf
7 3LTTzuhMqPLwQ4IGCwwugny6ZMtUQJSJ1
8 3F9495H8EJLb54wirgZkVgI47SP7M2RQWv
9 3JbrCyt7BdxRE9GX1N7GiEct8UnIjPmpYd
10 3H7vVTk4ejUbQXw45I6g5qvPBSe9bsjDqh
}
```
Any line beginning with `#` is a comment. Comments may be placed at the ends
of lines as well.
@ -283,22 +304,26 @@ Upon startup, older daemons will automatically generate a new default
Import your ten addresses into the new tracking wallet with the command:
$ mmgen-addrimport --batch my.addrs
```text
$ mmgen-addrimport --batch my.addrs
```
These addresses will now be tracked: any BTC transferred to them will show up in
your listing of address balances. Balances can be viewed using `mmgen-tool
listaddresses` (the `showempty` option requests addresses with empty balances
to be displayed too).
$ mmgen-tool listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
89ABCDEF:S:1 36bNmyYISiptuvJG3X7MPwiiS4HYvD7ksE Donations 0
89ABCDEF:S:2 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc Storage 1 0
89ABCDEF:S:3 3HgYCsfqYzIg7LVVfDTp7gYJocJEiDAy6N Storage 2 0
89ABCDEF:S:4 34Tu3z1tiexXDonNsFIkvzqutE5E3pTK8s Storage 3 0
89ABCDEF:S:5 3PeI55vtp2bX2uKDkAAR2c6ekHNYe4Hcq7 0
...
TOTAL: 0 BTC
```text
$ mmgen-tool listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
89ABCDEF:S:1 36bNmyYISiptuvJG3X7MPwiiS4HYvD7ksE Donations 0
89ABCDEF:S:2 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc Storage 1 0
89ABCDEF:S:3 3HgYCsfqYzIg7LVVfDTp7gYJocJEiDAy6N Storage 2 0
89ABCDEF:S:4 34Tu3z1tiexXDonNsFIkvzqutE5E3pTK8s Storage 3 0
89ABCDEF:S:5 3PeI55vtp2bX2uKDkAAR2c6ekHNYe4Hcq7 0
...
TOTAL: 0 BTC
```
*While not covered in this introduction, note that it’s also possible to [import
external coin addresses into your tracking wallet][01]. This allows you to
@ -318,13 +343,15 @@ them over the Bitcoin network. If you send 0.1, 0.2, 0.3 and 0.4 BTC
respectively, your address listing will look like this after the transactions
have confirmed:
$ mmgen-tool listaddresses
MMGenID COMMENT BALANCE
89ABCDEF:S:1 Donations 0.1
89ABCDEF:S:2 Storage 1 0.2
89ABCDEF:S:3 Storage 2 0.3
89ABCDEF:S:4 Storage 3 0.4
TOTAL: 1 BTC
```text
$ mmgen-tool listaddresses
MMGenID COMMENT BALANCE
89ABCDEF:S:1 Donations 0.1
89ABCDEF:S:2 Storage 1 0.2
89ABCDEF:S:3 Storage 2 0.3
89ABCDEF:S:4 Storage 3 0.4
TOTAL: 1 BTC
```
#### <a id="a_ct">Create a transaction (online computer)</a>
@ -339,7 +366,9 @@ To send 0.1 BTC to the a third-party address
`3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc`, for example, and send the change back to
yourself at address `89ABCDEF:S:5`, you’d issue the following command:
$ mmgen-txcreate 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 89ABCDEF:S:5
```text
$ mmgen-txcreate 3AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 89ABCDEF:S:5
```
`mmgen-txcreate` accepts either MMGen IDs or Bitcoin addresses as arguments.
@ -350,7 +379,9 @@ from the MMGen ID. Thus address `89ABCDEF:L:5` may be expressed as
To send 0.1 BTC to each of addresses `89ABCDEF:S:6` and `89ABCDEF:S:7`,
sending the change to `89ABCDEF:S:8`, you’d do this:
$ mmgen-txcreate 89ABCDEF:S:6,0.1 89ABCDEF:S:7,0.1 89ABCDEF:S:8
```text
$ mmgen-txcreate 89ABCDEF:S:6,0.1 89ABCDEF:S:7,0.1 89ABCDEF:S:8
```
As you can see, each address is followed by a comma and an amount, except for
the change address, for which the amount will be calculated automatically.
@ -367,20 +398,24 @@ criteria: transaction ID, address, amount and transaction age. Your overall
balance in BTC appears at the top of the screen. In our example, the display
will look something like this:
UNSPENT OUTPUTS (sort order: Age) Total BTC: 1
Num TX id Vout Address Amt(BTC) Age(d)
1) e9742b16... 5 3L3kxmi.. 89ABCDEF:S:1 Donations 0.1 1
2) fa84d709... 6 3N4dSGj.. 89ABCDEF:S:2 Storage 1 0.2 1
3) 8dde8ef5... 6 3M1fVDc.. 89ABCDEF:S:3 Storage 2 0.3 1
4) c76874c7... 0 3E8MFoC.. 89ABCDEF:S:4 Storage 3 0.4 1
```text
UNSPENT OUTPUTS (sort order: Age) Total BTC: 1
Num TX id Vout Address Amt(BTC) Age(d)
1) e9742b16... 5 3L3kxmi.. 89ABCDEF:S:1 Donations 0.1 1
2) fa84d709... 6 3N4dSGj.. 89ABCDEF:S:2 Storage 1 0.2 1
3) 8dde8ef5... 6 3M1fVDc.. 89ABCDEF:S:3 Storage 2 0.3 1
4) c76874c7... 0 3E8MFoC.. 89ABCDEF:S:4 Storage 3 0.4 1
Sort options: [t]xid, [a]mount, a[d]dress, [A]ge, [r]everse, [M]mgen addr
Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
'q'=quit view, 'p'=print to file, 'v'=pager view, 'w'=wide view, 'l'=add label:
Sort options: [t]xid, [a]mount, a[d]dress, [A]ge, [r]everse, [M]mgen addr
Display options: show [D]ays, [g]roup, show [m]mgen addr, r[e]draw screen
'q'=quit view, 'p'=print to file, 'v'=pager view, 'w'=wide view, 'l'=add label:
```
After quitting the menu with ‘q’, you’ll see the following prompt:
Enter a range or space-separated list of outputs to spend:
```text
Enter a range or space-separated list of outputs to spend:
```
Here you must choose unspent outputs of sufficient value to cover the send
amount of 0.1 BTC, plus the transaction fee (for more on fees, see ‘Transaction
@ -390,7 +425,9 @@ transaction fee, we’ll choose 0.0001 BTC (note that integer fees followed by
the letter ‘s’ for “satoshis per byte” are also permissible). After a couple
more prompts and confirmations, your transaction will be saved:
Transaction written to file 'FEDCBA[0.1].rawtx'
```text
Transaction written to file 'FEDCBA[0.1].rawtx'
```
The transaction filename consists of a unique MMGen Transaction ID plus the
non-change spend amount.
@ -403,9 +440,11 @@ and change addresses. This feature will be appreciated by privacy-conscious use
Now transfer the the raw transaction file to your offline computer and sign it
using your default wallet:
$ mmgen-txsign FEDCBA[0.1].rawtx
...
Signed transaction written to file 'FEDCBA[0.1].sigtx'
```text
$ mmgen-txsign FEDCBA[0.1].rawtx
...
Signed transaction written to file 'FEDCBA[0.1].sigtx'
```
Note that the signed transaction file has a new extension, `.sigtx`.
@ -416,9 +455,11 @@ network. Start bitcoind if it’s not already running, and make sure your
blockchain is fully synced. Then copy the signed transaction file to your
online computer and issue the command:
$ mmgen-txsend FEDCBA[0.1].sigtx
...
Transaction sent: abcd1234....
```text
$ mmgen-txsend FEDCBA[0.1].sigtx
...
Transaction sent: abcd1234....
```
Like all MMGen commands, `mmgen-txsend` is interactive, so you’ll be prompted
before the transaction is actually broadcast. If the send was successful, a
@ -428,25 +469,29 @@ in our case).
Once the transaction is broadcast to the network and confirmed, your address
listing should look something like this:
$ mmgen-tool listaddresses minconf=1
MMGenID COMMENT BALANCE
89ABCDEF:S:1 Donations 0.1
89ABCDEF:S:3 Storage 2 0.3
89ABCDEF:S:4 Storage 3 0.4
89ABCDEF:S:5 0.0999
TOTAL: 0.8999 BTC
```text
$ mmgen-tool listaddresses minconf=1
MMGenID COMMENT BALANCE
89ABCDEF:S:1 Donations 0.1
89ABCDEF:S:3 Storage 2 0.3
89ABCDEF:S:4 Storage 3 0.4
89ABCDEF:S:5 0.0999
TOTAL: 0.8999 BTC
```
Alternatively, you may use `mmgen-tool twview` or `mmgen-txcreate -i` for more
detailed and configurable output:
$ mmgen-tool twview
UNSPENT OUTPUTS (sort order: Age) Total BTC: 0.8999
Network: BTC MAINNET
Num TXid Vout Address Amt(BTC) Confs
1) e3c3.. 6 36bNmyYISiptuvJG3X7MPwii.. 89ABCDEF:S:1 Donations 0.1 68
2) face.. 6 3HgYCsfqYzIg7LVVfDTp7gYJ.. 89ABCDEF:S:3 Storage 2 0.3 68
3) abab.. 6 34Tu3z1tiexXDonNsFIkvzqu.. 89ABCDEF:S:4 Storage 3 0.4 68
4) 123c.. 6 3PeI55vtp2bX2uKDkAAR2c6e.. 89ABCDEF:S:5 0.0999 7
```text
$ mmgen-tool twview
UNSPENT OUTPUTS (sort order: Age) Total BTC: 0.8999
Network: BTC MAINNET
Num TXid Vout Address Amt(BTC) Confs
1) e3c3.. 6 36bNmyYISiptuvJG3X7MPwii.. 89ABCDEF:S:1 Donations 0.1 68
2) face.. 6 3HgYCsfqYzIg7LVVfDTp7gYJ.. 89ABCDEF:S:3 Storage 2 0.3 68
3) abab.. 6 34Tu3z1tiexXDonNsFIkvzqu.. 89ABCDEF:S:4 Storage 3 0.4 68
4) 123c.. 6 3PeI55vtp2bX2uKDkAAR2c6e.. 89ABCDEF:S:5 0.0999 7
```
Since you’ve sent 0.1 BTC to a third party, your balance has decreased by 0.1
BTC plus the transaction fee of 0.0001 BTC.
@ -460,14 +505,16 @@ of MMGen’s more advanced features, continue reading.
Using your default wallet from the exercises above, generate a mnemonic:
$ mmgen-walletconv -o words
...
Mnemonic data written to file '89ABCDEF.mmwords'
```text
$ mmgen-walletconv -o words
...
Mnemonic data written to file '89ABCDEF.mmwords'
$ cat 89ABCDEF.mmwords
pleasure tumble spider laughter many stumble secret bother after search
float absent path strong curtain savior worst suspend bright touch away
dirty measure thorn
$ cat 89ABCDEF.mmwords
pleasure tumble spider laughter many stumble secret bother after search
float absent path strong curtain savior worst suspend bright touch away
dirty measure thorn
```
Since our seed is 256 bits long, the mnemonic contains 24 words. 128-bit and
192-bit seeds generate shorter mnemonics of 12 and 18 words, respectively.
@ -485,21 +532,27 @@ The mnemonic is a complete representation of your seed and may be used anywhere
where you’d use an MMGen wallet. You can generate addresses with it just as you
do with a wallet:
$ mmgen-addrgen --type=segwit 89ABCDEF.mmwords 1-10
...
Address data written to file '89ABCDEF-S[1-10].addrs'
```text
$ mmgen-addrgen --type=segwit 89ABCDEF.mmwords 1-10
...
Address data written to file '89ABCDEF-S[1-10].addrs'
```
You can use it to sign transactions:
$ mmgen-txsign FEDCBA[0.1].rawtx 89ABCDEF.mmwords
...
Signed transaction written to file 'FEDCBA[0.1].sigtx'
```text
$ mmgen-txsign FEDCBA[0.1].rawtx 89ABCDEF.mmwords
...
Signed transaction written to file 'FEDCBA[0.1].sigtx'
```
The mnemonic can also be used to regenerate a lost wallet:
$ mmgen-walletconv 89ABCDEF.mmwords
...
MMGen wallet written to file '89ABCDEF-01234567[256,3].mmdat'
```text
$ mmgen-walletconv 89ABCDEF.mmwords
...
MMGen wallet written to file '89ABCDEF-01234567[256,3].mmdat'
```
Note that the regenerated wallet has a different Key ID but of course the same
Seed ID.
@ -508,50 +561,66 @@ An alternative to mnemonics, seed files provide yet another way of representing
your seed. They bear the extension `.mmseed` and are generated exactly the same
way as mnemonic files:
$ mmgen-walletconv -o seed
...
Seed data written to file '89ABCDEF.mmseed'
```text
$ mmgen-walletconv -o seed
...
Seed data written to file '89ABCDEF.mmseed'
```
They can be used just like mnemonics to regenerate a wallet:
$ mmgen-walletconv 89ABCDEF.mmseed
...
MMGen wallet written to file '89ABCDEF-23456701[256,3].mmdat'
```text
$ mmgen-walletconv 89ABCDEF.mmseed
...
MMGen wallet written to file '89ABCDEF-23456701[256,3].mmdat'
```
Here’s a sample seed file for a 256-bit seed:
$ cat 8B7392ED.mmseed
f4c84b C5ZT wWpT Jsoi wRVw 2dm9 Aftd WLb8 FggQ eC8h Szjd da9L
```text
$ cat 8B7392ED.mmseed
f4c84b C5ZT wWpT Jsoi wRVw 2dm9 Aftd WLb8 FggQ eC8h Szjd da9L
```
And for a 128-bit seed:
$ cat 8E0DFB78.mmseed
0fe02f XnyC NfPH piuW dQ2d nM47 VU
```text
$ cat 8E0DFB78.mmseed
0fe02f XnyC NfPH piuW dQ2d nM47 VU
```
As you can see, seed files are short enough to be easily written out by hand or
memorized. And their built-in checksum makes it easy to test your memory using
a simple Unix shell command:
$ echo -n XnyC NfPH piuW dQ2d nM47 VU | tr -d ' '| sha256sum | cut -c 1-6
0fe02f
```text
$ echo -n XnyC NfPH piuW dQ2d nM47 VU | tr -d ' '| sha256sum | cut -c 1-6
0fe02f
```
Or you can do the same thing with `mmgen-tool`:
$ mmgen-tool str2id6 'XnyC NfPH piuW dQ2d nM47 VU'
0fe02f
```text
$ mmgen-tool str2id6 'XnyC NfPH piuW dQ2d nM47 VU'
0fe02f
```
Beginning with version 0.9.0, MMGen also supports seed files in hexadecimal
(hexseed) format. Hexseed files are identical to seed files but encoded in
hexadecimal rather than base 58. They bear the extension `.mmhex`:
$ cat FE3C6545.mmhex
afc3fe 456d 7f5f 1c4b fe3b c916 b875 60ae 6a3e
```text
$ cat FE3C6545.mmhex
afc3fe 456d 7f5f 1c4b fe3b c916 b875 60ae 6a3e
```
You can easily check that a hexseed is correct by generating its Seed ID with
standard command-line tools:
$ echo 456d 7f5f 1c4b fe3b c916 b875 60ae 6a3e | tr -d ' ' | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | cut -c 1-8
fe3c6545
```text
$ echo 456d 7f5f 1c4b fe3b c916 b875 60ae 6a3e | tr -d ' ' | xxd -r -p | sha256sum -b | xxd -r -p | sha256sum -b | cut -c 1-8
fe3c6545
```
Mnemonics and hexseeds can be used to generate keys even without the MMGen
software, using basic command-line utilities, as explained in [this
@ -565,12 +634,14 @@ store your seed entirely in your head if you wish and never record it on a
physical medium. To input your seed data at the prompt, just specify an input
format instead of a file name:
$ mmgen-addrgen -i words 1-10
...
Choose a mnemonic length: 1) 12 words, 2) 18 words, 3) 24 words: 1
Mnemonic length of 12 words chosen. OK? (Y/n): y
Enter your 12-word mnemonic, hitting RETURN or SPACE after each word:
Enter word #1:
```text
$ mmgen-addrgen -i words 1-10
...
Choose a mnemonic length: 1) 12 words, 2) 18 words, 3) 24 words: 1
Mnemonic length of 12 words chosen. OK? (Y/n): y
Enter your 12-word mnemonic, hitting RETURN or SPACE after each word:
Enter word #1:
```
Here MMGen prompts you interactively for each word of the seed phrase, checking
it for validity and reprompting if necessary. The words are not displayed on
@ -595,11 +666,15 @@ Interactive dieroll wallet generation works just like the interactive mnemonic
input described in the preceding section. To generate a new dieroll wallet,
type:
$ mmgen-walletconv -i dieroll
```text
$ mmgen-walletconv -i dieroll
```
To save the wallet in a format of your choice, use the `-o` option:
$ mmgen-walletconv -i dieroll -o bip39
```text
$ mmgen-walletconv -i dieroll -o bip39
```
50, 75 and 100 rolls of the die are required to create 128, 192 and 256-bit
seeds, respectively.
@ -612,11 +687,15 @@ described above. Just use the `bip39` format specifier and extension instead of
Convert an MMGen native mnemonic wallet to BIP39:
$ mmgen-walletconv -o bip39 mywallet.words
```text
$ mmgen-walletconv -o bip39 mywallet.words
```
Restore an MMGen wallet from a BIP39 seed phrase in a file:
$ mmgen-walletconv seed.bip39
```text
$ mmgen-walletconv seed.bip39
```
#### <a id="a_mm">Monero mnemonic support</a>
@ -630,12 +709,16 @@ to be canonical.
Generate a random Monero seed phrase:
$ mmgen-tool mn_rand256 fmt=xmrseed
```text
$ mmgen-tool mn_rand256 fmt=xmrseed
```
Generate a list of passwords in Monero mnemonic format with ID 'foo' from your
default wallet:
$ mmgen-passgen -f xmrseed 'foo' 1-10
```text
$ mmgen-passgen -f xmrseed 'foo' 1-10
```
#### <a id="a_ic">Incognito wallets</a>
@ -655,28 +738,32 @@ If you plan to store your incognito wallet in an insecure location such as cloud
storage, you’re advised to use a strong scrypt (hash) preset and a strong
password. These can be changed using the `mmgen-passchg` utility:
$ mmgen-passchg -p 5 89ABCDEF-01234567[256,3].mmdat
...
Hash preset of wallet: '3'
Enter old passphrase for MMGen wallet: <old weak passphrase>
...
Hash preset changed to '5'
Enter new passphrase for MMGen wallet: <new strong passphrase>
...
MMGen wallet written to file '89ABCDEF-87654321[256,5].mmdat'
```text
$ mmgen-passchg -p 5 89ABCDEF-01234567[256,3].mmdat
...
Hash preset of wallet: '3'
Enter old passphrase for MMGen wallet: <old weak passphrase>
...
Hash preset changed to '5'
Enter new passphrase for MMGen wallet: <new strong passphrase>
...
MMGen wallet written to file '89ABCDEF-87654321[256,5].mmdat'
```
The scrypt preset is the numeral in the wallet filename following the seed
length. As you can see, it’s now changed to `5`. Now export your new toughened
wallet to incognito format, using the `-k` option to leave the passphrase
unchanged:
$ mmgen-walletconv -k -o incog 89ABCDEF-87654321[256,5].mmdat
...
Reusing passphrase at user request
...
New Incog Wallet ID: ECA86420
...
Incognito data written to file '89ABCDEF-87654321-ECA86420[256,5].mmincog'
```text
$ mmgen-walletconv -k -o incog 89ABCDEF-87654321[256,5].mmdat
...
Reusing passphrase at user request
...
New Incog Wallet ID: ECA86420
...
Incognito data written to file '89ABCDEF-87654321-ECA86420[256,5].mmincog'
```
Incog wallets have a special identifier, the Incog ID, which can be used to
locate the wallet data if you’ve forgotten where you hid it (see the example
@ -685,15 +772,19 @@ should be kept secret.
Incog wallets can also be output to hexadecimal format:
$ mmgen-walletconv -k -o incox 89ABCDEF-87654321[256,5].mmdat
...
Hex incognito data written to file '89ABCDEF-87654321-CA86420E[256,5].mmincox'
```text
$ mmgen-walletconv -k -o incox 89ABCDEF-87654321[256,5].mmdat
...
Hex incognito data written to file '89ABCDEF-87654321-CA86420E[256,5].mmincox'
```
$ cat 89ABCDEF-87654321-1EE402F4[256,5].mmincox
6772 edb2 10cf ad0d c7dd 484b cc7e 42e9
4fe6 e07a 1ce2 da02 6da7 94e4 c068 57a8
3706 c5ce 56e0 7590 e677 6c6e 750a d057
b43a 21f9 82c7 6bd1 fe96 bad9 2d54 c4c0
```text
$ cat 89ABCDEF-87654321-1EE402F4[256,5].mmincox
6772 edb2 10cf ad0d c7dd 484b cc7e 42e9
4fe6 e07a 1ce2 da02 6da7 94e4 c068 57a8
3706 c5ce 56e0 7590 e677 6c6e 750a d057
b43a 21f9 82c7 6bd1 fe96 bad9 2d54 c4c0
```
Note that the Incog ID is different here: it’s generated from an init vector,
which is a different random number each time, making the incog data as a whole
@ -706,14 +797,16 @@ the wrong hands.
Your incognito wallet (whether hex or binary) can be used just like any other
MMGen wallet, mnemonic or seed file to generate addresses and sign transactions:
$ mmgen-addrgen --type=segwit 89ABCDEF-87654321-CA86420E[256,5].mmincox 101-110
...
Generated 10 addresses
Addresses written to file '89ABCDEF-S[101-110].addrs'
```text
$ mmgen-addrgen --type=segwit 89ABCDEF-87654321-CA86420E[256,5].mmincox 101-110
...
Generated 10 addresses
Addresses written to file '89ABCDEF-S[101-110].addrs'
$ mmgen-txsign FABCDE[0.3].rawtx 89ABCDEF-87654321-CA86420E[256,5].mmincox
...
Signed transaction written to file FABCDE[0.3].sigtx
$ mmgen-txsign FABCDE[0.3].rawtx 89ABCDEF-87654321-CA86420E[256,5].mmincox
...
Signed transaction written to file FABCDE[0.3].sigtx
```
##### <a id="a_hi">Hidden incognito wallets</a>
@ -722,14 +815,16 @@ a specified offset in a file or partition in a single convenient operation, with
the random file being created automatically if necessary. Here’s how you’d
create a 1GB file `random.dat` and hide a wallet in it at offset `123456789`:
$ mmgen-walletconv -k -o hincog -J random.dat,123456789 89ABCDEF-87654321[256,5].mmdat
...
New Incog Wallet ID: ED1F2ACB
...
Requested file 'random.dat' does not exist. Create? (Y/n): Y
Enter file size: 1G
...
Data written to file 'random.dat' at offset 123456789
```text
$ mmgen-walletconv -k -o hincog -J random.dat,123456789 89ABCDEF-87654321[256,5].mmdat
...
New Incog Wallet ID: ED1F2ACB
...
Requested file 'random.dat' does not exist. Create? (Y/n): Y
Enter file size: 1G
...
Data written to file 'random.dat' at offset 123456789
```
Your ‘random’ file can now be uploaded to a cloud storage service, for example,
or some other, preferably non-public, location on the Internet (in a real-life
@ -740,9 +835,11 @@ Now let’s say at some point in the future you download this file to recover
your wallet and realize you’ve forgotten the offset where the data is hidden.
If you’ve saved your Incog ID, you’re in luck:
$ mmgen-tool find_incog_data random.dat ED1F2ACB
...
Incog data for ID ED1F2ACB found at offset 123456789
```text
$ mmgen-tool find_incog_data random.dat ED1F2ACB
...
Incog data for ID ED1F2ACB found at offset 123456789
```
The search process can be slow, so patience is required. In addition, on
large files ‘false positives’ are a distinct possibility, in which case you’ll
@ -752,13 +849,17 @@ real offset.
Hidden incog wallets are nearly as convenient to use as ordinary ones.
Generating ten addresses with your hidden incog data is as easy as this:
$ mmgen-addrgen -H random.dat,123456789 101-110
```text
$ mmgen-addrgen -H random.dat,123456789 101-110
```
Transaction signing uses the same syntax:
$ mmgen-txsign -H random.dat,123456789 ABCDEF[0.1].rawtx
...
Signed transaction written to file 'ABCDEF[0.1].sigtx'
```text
$ mmgen-txsign -H random.dat,123456789 ABCDEF[0.1].rawtx
...
Signed transaction written to file 'ABCDEF[0.1].sigtx'
```
### <a id="a_at">Advanced Topics</a>
@ -786,16 +887,20 @@ guide, generate a subwallet on your offline machine for use as a hot wallet.
Since this wallet is going to be used in an online environment, make sure it’s
protected with a strong password and hash preset.
$ mmgen-subwalletgen -p5 1L
...
MMGen wallet written to file 'FC9A8735-ABCDEF00[256,5].mmdat'
```text
$ mmgen-subwalletgen -p5 1L
...
MMGen wallet written to file 'FC9A8735-ABCDEF00[256,5].mmdat'
```
Copy the subwallet to a USB stick or other removable device.
Now on your online computer, check your MMGen data directory for the presence of
wallet files:
$ ls $HOME/.mmgen/*.mmdat
```text
$ ls $HOME/.mmgen/*.mmdat
```
If any are present (there shouldn’t be if you’ve been following this guide!),
move them out of harm’s way, or copy them to a backup location and securely
@ -804,15 +909,19 @@ delete the originals with `wipe` or `sdelete` if they’re securing any funds.
Copy the subwallet file to your MMGen data directory, making it your default
wallet for the online machine:
$ cp 'FC9A8735-ABCDEF00[256,5].mmdat' $HOME/.mmgen
```text
$ cp 'FC9A8735-ABCDEF00[256,5].mmdat' $HOME/.mmgen
```
Securely delete the original file.
Generate a range of addresses with your online default wallet/subwallet and
import them into your tracking wallet:
$ mmgen-addrgen --type=bech32 1-10
$ mmgen-addrimport FC9A8735-B*.addrs
```text
$ mmgen-addrgen --type=bech32 1-10
$ mmgen-addrimport FC9A8735-B*.addrs
```
Send some coins to an address or addresses in this range using your method of
choice.
@ -820,10 +929,12 @@ choice.
Now you can spend from these addresses using `mmgen-txdo`, creating, signing
and sending transactions in one operation:
$ mmgen-txdo 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 FC9A8735:S:2
(choose an input from wallet FC9A8735)
...
Transaction sent: abcd1234....
```text
$ mmgen-txdo 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 FC9A8735:S:2
(choose an input from wallet FC9A8735)
...
Transaction sent: abcd1234....
```
Bear in mind that your subwallet/online default wallet doesn’t require a backup,
as it can always be regenerated from its offline parent. If you ever wish to
@ -879,11 +990,13 @@ incrementally increasing fees will created online and then signed offline.
Create, sign and send a BIP 125 replaceable transaction with a fee of 50
satoshis per byte:
$ mmgen-txdo --rbf --tx-fee 50s 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 0FDE89AB:S:5
...
Signed transaction written to file 'FEDCBB[0.1,50].sigtx'
...
Transaction sent: dcba4321....
```text
$ mmgen-txdo --rbf --tx-fee 50s 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 0FDE89AB:S:5
...
Signed transaction written to file 'FEDCBB[0.1,50].sigtx'
...
Transaction sent: dcba4321....
```
Here you’ve sent 0.1 BTC to a third-party address and the change back to
yourself at address #5 of your default hot wallet with Seed ID `0FDE89AB`.
@ -894,11 +1007,13 @@ of the fee in the filename identifies the transaction as replaceable.
If the transaction fails to confirm in your desired timeframe, then create, sign
and send a replacement transaction with a higher fee, say 100 satoshis per byte:
$ mmgen-txbump --send --tx-fee 100s --output-to-reduce c 'FEDCBB[0.1,50].sigtx'
...
Signed transaction written to file 'DAE123[0.1,100].sigtx'
...
Transaction sent: eef01357....
```text
$ mmgen-txbump --send --tx-fee 100s --output-to-reduce c 'FEDCBB[0.1,50].sigtx'
...
Signed transaction written to file 'DAE123[0.1,100].sigtx'
...
Transaction sent: eef01357....
```
The `--send` switch instructs `mmgen-txbump` to sign and send the transaction
after creating it. The `--output-to-reduce` switch with an argument of `c`
@ -918,38 +1033,48 @@ non-essential prompts.
To achieve the same result as in the above example using a cold wallet, just
create the initial transaction with `mmgen-txcreate` instead of `mmgen-txdo`:
$ mmgen-txcreate --rbf --tx-fee 50s 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 89ABCDEF:S:5
...
Transaction written to file 'FEDCBC[0.1,50].rawtx'
```text
$ mmgen-txcreate --rbf --tx-fee 50s 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 89ABCDEF:S:5
...
Transaction written to file 'FEDCBC[0.1,50].rawtx'
```
Now create a series of transactions with incrementally increasing fees for
offline signing:
$ mmgen-txbump --tx-fee 100s --output-to-reduce c 'FEDCBC[0.1,50].rawtx'
$ mmgen-txbump --tx-fee 150s --output-to-reduce c 'FEDCBC[0.1,50].rawtx'
$ mmgen-txbump --tx-fee 200s --output-to-reduce c 'FEDCBC[0.1,50].rawtx'
```text
$ mmgen-txbump --tx-fee 100s --output-to-reduce c 'FEDCBC[0.1,50].rawtx'
$ mmgen-txbump --tx-fee 150s --output-to-reduce c 'FEDCBC[0.1,50].rawtx'
$ mmgen-txbump --tx-fee 200s --output-to-reduce c 'FEDCBC[0.1,50].rawtx'
```
To speed things up, add the `--yes` switch to make `mmgen-txbump` completely
non-interactive.
The result will be four raw transaction files with increasing fees, like this:
FEDCBC[0.1,50].rawtx
3EBB00[0.1,100].rawtx
124FFF[0.1,150].rawtx
73DABB[0.1,200].rawtx
```text
FEDCBC[0.1,50].rawtx
3EBB00[0.1,100].rawtx
124FFF[0.1,150].rawtx
73DABB[0.1,200].rawtx
```
Copy the files to an empty folder, transfer the folder to your offline machine and batch sign them:
$ mmgen-txsign -d my_folder --yes my_folder/*.rawtx
```text
$ mmgen-txsign -d my_folder --yes my_folder/*.rawtx
```
Then copy the signed transaction files back to your online machine and broadcast
them in turn until you get a confirmation:
$ mmgen-txsend FEDCBC[0.1,50].sigtx # ...if this doesn’t confirm, then
$ mmgen-txsend 3EBB00[0.1,100].sigtx # ...if this doesn’t confirm, then
$ mmgen-txsend 124FFF[0.1,150].sigtx # ...if this doesn’t confirm, then
$ mmgen-txsend 73DABB[0.1,200].sigtx
```text
$ mmgen-txsend FEDCBC[0.1,50].sigtx # ...if this doesn’t confirm, then
$ mmgen-txsend 3EBB00[0.1,100].sigtx # ...if this doesn’t confirm, then
$ mmgen-txsend 124FFF[0.1,150].sigtx # ...if this doesn’t confirm, then
$ mmgen-txsend 73DABB[0.1,200].sigtx
```
#### <a id="a_utd">Keeping your installation up to date</a>
@ -961,20 +1086,26 @@ on a periodic basis.
If you’ve deleted or lost your local copy of the MMGen repository, clone it
again from Github or Gitlab:
$ git clone https://github.com/mmgen/mmgen.git # Github
$ git clone https://gitlab.com/mmgen/mmgen.git # Gitlab
```text
$ git clone https://github.com/mmgen/mmgen.git # Github
$ git clone https://gitlab.com/mmgen/mmgen.git # Gitlab
```
Enter the repository and check out the master branch. Pull the latest changes
from the remote repository:
$ cd mmgen
$ git checkout master
$ git pull
```text
$ cd mmgen
$ git checkout master
$ git pull
```
Check out the current stable version for your operating system:
$ git checkout stable_linux # for Linux-based systems
$ git checkout stable_msys2 # for Microsoft Windows / MSYS2 systems
```text
$ git checkout stable_linux # for Linux-based systems
$ git checkout stable_msys2 # for Microsoft Windows / MSYS2 systems
```
Note that if you want to try out the latest “bleeding edge” (and possibly
unstable) features, you can just remain on the master branch and omit the
@ -984,9 +1115,11 @@ preceding step. Information on recently added features can be found by typing
Check the latest release notes in `doc/release-notes` and make note of any new
features or requirements. Now build and install:
$ rm -rf dist build
$ python3 -m build --no-isolation
$ python3 -m pip install --user --upgrade dist/*.whl
```text
$ rm -rf dist build
$ python3 -m build --no-isolation
$ python3 -m pip install --user --upgrade dist/*.whl
```
[01]: Tracking-and-spending-ordinary-Bitcoin-addresses
[02]: https://tpfaucet.appspot.com

@ -7,27 +7,35 @@ binaries are available for Bitcoin Core, Bitcoin ABC and Litecoin. See the
> Make sure the required boost library development packages are installed:
sudo apt-get install libboost-system-dev libboost-filesystem-dev libboost-program-options-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
```text
sudo apt-get install libboost-system-dev libboost-filesystem-dev libboost-program-options-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev
```
> You’ll also need the following standard dependencies, if they’re not already on
> your system:
sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libdb-dev libdb++-dev libevent-dev
```text
sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libdb-dev libdb++-dev libevent-dev
```
### Compile and install Bitcoin Core:
> Clone the Bitcoin Core repository from Github:
$ git clone https://github.com/bitcoin/bitcoin.git
$ cd bitcoin
```text
$ git clone https://github.com/bitcoin/bitcoin.git
$ cd bitcoin
```
> Configure and build:
$ git tag # look for your desired version in the tag list
$ git checkout <version>
$ ./autogen.sh
$ ./configure --without-gui --with-incompatible-bdb
$ make -j4
```text
$ git tag # look for your desired version in the tag list
$ git checkout <version>
$ ./autogen.sh
$ ./configure --without-gui --with-incompatible-bdb
$ make -j4
```
> The '-j4' option will speed the build process up by using 4 cores of a 4-core
> processor, if you have them. If overheating issues are a problem for your CPU
@ -40,16 +48,20 @@ binaries are available for Bitcoin Core, Bitcoin ABC and Litecoin. See the
> Your freshly compiled bitcoind daemon is now in the src/ directory. Install
> it, along with the 'bitcoin-cli' utility, into your executable path:
$ cd src
$ sudo install -sv bitcoind bitcoin-cli /usr/local/bin
```text
$ cd src
$ sudo install -sv bitcoind bitcoin-cli /usr/local/bin
```
### Compile and install Bitcoin Cash Node (optional):
> If you want to transact BCH, also known as “Bitcoin Cash Node”, then first
> clone the Bitcoin Cash Node repository:
$ git clone https://github.com/bitcoin-cash-node/bitcoin-cash-node
$ cd bitcoin-cash-node
```text
$ git clone https://github.com/bitcoin-cash-node/bitcoin-cash-node
$ cd bitcoin-cash-node
```
> Then configure and build using the same configure and build steps as with
> Bitcoin Core above.
@ -57,8 +69,10 @@ binaries are available for Bitcoin Core, Bitcoin ABC and Litecoin. See the
> The resulting executable is also named 'bitcoind', so you must install it
> under a different name to avoid overwriting your Core daemon:
$ cd src
$ sudo install -sv bitcoind /usr/local/bin/bitcoind-bchn
```text
$ cd src
$ sudo install -sv bitcoind /usr/local/bin/bitcoind-bchn
```
> From now on, you’ll invoke the daemon as 'bitcoind-bchn' instead of 'bitcoind'.
@ -66,14 +80,18 @@ binaries are available for Bitcoin Core, Bitcoin ABC and Litecoin. See the
> Clone the Litecoin Core repository:
$ git clone https://github.com/litecoin-project/litecoin.git
$ cd litecoin
```text
$ git clone https://github.com/litecoin-project/litecoin.git
$ cd litecoin
```
> Configure and build using the configure and build steps for Bitcoin Core,
> and then install as follows:
$ cd src
$ sudo install -sv litecoind litecoin-cli /usr/local/bin
```text
$ cd src
$ sudo install -sv litecoind litecoin-cli /usr/local/bin
```
Refer to [Run][02] on the binary installation page for instructions on running
your coin daemon(s).
@ -82,8 +100,10 @@ Alternatively, you may download and use the node start and stop scripts from the
MMGenLive project, which simplify starting and stopping multiple daemons on the
same machine:
$ curl -O 'https://raw.githubusercontent.com/mmgen/MMGenLive/master/home.mmgen/bin/mmlive-node-{start,stop}'
$ sudo install -v mmlive-node-{start,stop} /usr/local/bin
```text
$ curl -O 'https://raw.githubusercontent.com/mmgen/MMGenLive/master/home.mmgen/bin/mmlive-node-{start,stop}'
$ sudo install -v mmlive-node-{start,stop} /usr/local/bin
```
[01]: Install-Bitcoind
[02]: Install-Bitcoind#a_r

@ -77,15 +77,17 @@ more low-powered computer as your online machine.
>> background, so to run multiple daemons simultaneously you must start each
>> one in a separate terminal window. Start your daemons like this:
# Bitcoin Core:
$ bitcoind
```text
# Bitcoin Core:
$ bitcoind
# Bitcoin Cash Node:
$ mkdir $APPDATA/Bitcoin-Cash-Node
$ bitcoind-bchn --listen=0 --rpcport=8442 --datadir=$APPDATA/Bitcoin-Cash-Node --usecashaddr=0
# Bitcoin Cash Node:
$ mkdir $APPDATA/Bitcoin-Cash-Node
$ bitcoind-bchn --listen=0 --rpcport=8442 --datadir=$APPDATA/Bitcoin-Cash-Node --usecashaddr=0
# Litecoin
$ litecoind
# Litecoin
$ litecoind
```
>> Note that the `--listen=0` argument is required only when running Bitcoin
>> Core and Bitcoin Cash Node simultaneously.
@ -94,26 +96,30 @@ more low-powered computer as your online machine.
>> Linux users start their daemons like this:
# Bitcoin Core:
$ bitcoind --daemon
```text
# Bitcoin Core:
$ bitcoind --daemon
# Bitcoin Cash Node:
$ mkdir ~/.bitcoin-bchn
$ bitcoind-bchn --daemon --listen=0 --rpcport=8442 --datadir=$HOME/.bitcoin-bchn --usecashaddr=0
# Bitcoin Cash Node:
$ mkdir ~/.bitcoin-bchn
$ bitcoind-bchn --daemon --listen=0 --rpcport=8442 --datadir=$HOME/.bitcoin-bchn --usecashaddr=0
# Litecoin:
$ litecoind --daemon
# Litecoin:
$ litecoind --daemon
```
> Communicate with your daemons like this:
# Core:
$ bitcoin-cli help
```text
# Core:
$ bitcoin-cli help
# Bitcoin Cash Node:
$ bitcoin-cli-bchn --rpcport=8442 help
# Bitcoin Cash Node:
$ bitcoin-cli-bchn --rpcport=8442 help
# Litecoin:
$ litecoin-cli help
# Litecoin:
$ litecoin-cli help
```
> Warning: If you’re using an existing Bitcoin or Litecoin installation, **move
> your wallet.dat out of harm’s way** before starting the daemon. The new

@ -10,27 +10,35 @@ For computers with no Internet connection, see **Note for offline machines** bel
##### Debian/Ubuntu:
$ sudo apt-get install curl git gcc libtool make autoconf libgmp-dev libssl-dev libpcre3-dev libmpfr-dev libmpc-dev python3-dev python3-pip
```text
$ sudo apt-get install curl git gcc libtool make autoconf libgmp-dev libssl-dev libpcre3-dev libmpfr-dev libmpc-dev python3-dev python3-pip
```
##### Arch Linux:
$ sudo pacman -S curl git gcc libtool make autoconf automake autogen pcre python-pip
```text
$ sudo pacman -S curl git gcc libtool make autoconf automake autogen pcre python-pip
```
#### Upgrade the build tools:
$ python3 -m pip install --user --upgrade pip setuptools build wheel
```text
$ python3 -m pip install --user --upgrade pip setuptools build wheel
```
#### Install MMGen:
Make sure that `~/.local/bin` is in `PATH`. Existing MMGen users should delete
any old installations under `/usr` or `/usr/local`.
$ git clone https://github.com/mmgen/mmgen.git
$ cd mmgen
$ git checkout stable_linux # see 'Note' below
$ python3 -m build --no-isolation
$ python3 -m pip install --user --upgrade dist/*.whl # see 'Install Note' below
$ cd ..
```text
$ git clone https://github.com/mmgen/mmgen.git
$ cd mmgen
$ git checkout stable_linux # see 'Note' below
$ python3 -m build --no-isolation
$ python3 -m pip install --user --upgrade dist/*.whl # see 'Install Note' below
$ cd ..
```
**Note:** if you want to use features that have appeared since the latest
`stable_linux` release, then you can omit the `git checkout` step and remain on

@ -6,10 +6,10 @@
* [1. Install MSYS2](#a_ms)
* [2. Set up PowerShell as your MSYS2 terminal](#a_ps)
* [3. Upgrade MSYS2](#a_ug)
* [Online users](#a_ug1)
* [Offline install](#a_ug2)
* [Online users](#a_ug1)
* [Offline install](#a_ug2)
* [4. Install MSYS2 MMGen dependencies](#a_md)
* [Offline install](#a_md1)
* [Offline install](#a_md1)
* [5. Set up your environment](#a_ev)
* [6. Install the Python ECDSA library (offline install only)](#a_ec)
* [7. Install the standalone scrypt package (required for strong password hashing)](#a_sc)
@ -79,9 +79,10 @@ PowerShell. From now on, all your work will be done in this terminal.
Note that the root of your MSYS2 installation is located in `C:\\msys64`, so the
following commands, for example, will produce a listing of the same directory:
$ ls /etc # the path as seen within MSYS2
$ ls 'C:\\msys64\etc' # the path as seen by Windows
```text
$ ls /etc # the path as seen within MSYS2
$ ls 'C:\\msys64\etc' # the path as seen by Windows
```
### <a id="a_ug">3. Upgrade MSYS2</a>
@ -91,7 +92,9 @@ following commands, for example, will produce a listing of the same directory:
> Update the package database and core system packages:
$ pacman -Syu
```text
$ pacman -Syu
```
> Exit and restart the terminal. If you’re using modified mirror lists, they
> may have been overwritten by the update operation, in which case you should
@ -99,7 +102,9 @@ following commands, for example, will produce a listing of the same directory:
> Now complete upgrading the system:
$ pacman -Su
```text
$ pacman -Su
```
#### <a id="a_ug2">Offline install:</a>
@ -115,13 +120,17 @@ following commands, for example, will produce a listing of the same directory:
> first in the list. For this you may use a text editor such as Notepad or
> Nano:
$ nano /etc/pacman.d/mirrorlist.msys
... repeat for remaining mirrorlist files ...
```text
$ nano /etc/pacman.d/mirrorlist.msys
... repeat for remaining mirrorlist files ...
```
> You need to update your database files as well. The database files and their
> associated signature files can be listed by issuing the following command:
$ ls /var/lib/pacman/sync
```text
$ ls /var/lib/pacman/sync
```
> Download up-to-date versions of these files from a fast MSYS2 mirror:
@ -143,7 +152,9 @@ following commands, for example, will produce a listing of the same directory:
> Now issue the following command:
$ pacman -Sup > urls.txt
```text
$ pacman -Sup > urls.txt
```
> This command may cause your MSYS terminal window to close. If so, just
> reopen another one.
@ -154,14 +165,18 @@ following commands, for example, will produce a listing of the same directory:
> Create a new folder on your offline machine:
$ mkdir packages1
```text
$ mkdir packages1
```
Transfer the downloaded package files to the offline machine and place them in
this folder.
> Now issue the following command to install the packages:
$ pacman -U packages1/*
```text
$ pacman -U packages1/*
```
> When the process is finished, close your terminal window and reopen another
> one.
@ -189,42 +204,50 @@ specifically required by MMGen.
Install the MMGen requirements and their dependencies:
$ pacman -S tar git vim autoconf automake-wrapper autogen libtool cygrunsrv \
mingw-w64-x86_64-python-build \
mingw-w64-x86_64-python-wheel \
mingw-w64-x86_64-python-pip \
mingw-w64-x86_64-libltdl \
mingw-w64-x86_64-gcc \
mingw-w64-x86_64-make \
mingw-w64-x86_64-pcre \
mingw-w64-x86_64-libsodium \
mingw-w64-x86_64-python-cryptography \
mingw-w64-x86_64-python-six \
mingw-w64-x86_64-python-pexpect \
mingw-w64-x86_64-python-gmpy2 \
mingw-w64-x86_64-python-pynacl \
mingw-w64-x86_64-python-pysocks \
mingw-w64-x86_64-python-requests \
mingw-w64-x86_64-python-aiohttp \
mingw-w64-x86_64-python-pyreadline3
```text
$ pacman -S tar git vim autoconf automake-wrapper autogen libtool cygrunsrv \
mingw-w64-x86_64-python-build \
mingw-w64-x86_64-python-wheel \
mingw-w64-x86_64-python-pip \
mingw-w64-x86_64-libltdl \
mingw-w64-x86_64-gcc \
mingw-w64-x86_64-make \
mingw-w64-x86_64-pcre \
mingw-w64-x86_64-libsodium \
mingw-w64-x86_64-python-cryptography \
mingw-w64-x86_64-python-six \
mingw-w64-x86_64-python-pexpect \
mingw-w64-x86_64-python-gmpy2 \
mingw-w64-x86_64-python-pynacl \
mingw-w64-x86_64-python-pysocks \
mingw-w64-x86_64-python-requests \
mingw-w64-x86_64-python-aiohttp \
mingw-w64-x86_64-python-pyreadline3
```
### <a id="a_ev">5. Set up your environment</a>
Create the `/usr/local/bin` directory. This is where you’ll place various
binaries required by MMGen:
$ mkdir -p /usr/local/bin # seen by Windows as 'C:\\msys64\usr\local\bin'
```text
$ mkdir -p /usr/local/bin # seen by Windows as 'C:\\msys64\usr\local\bin'
```
Open your shell’s runtime configuration file in a text editor:
$ nano ~/.bashrc
```text
$ nano ~/.bashrc
```
Add the following two lines to the end of the file (if this is a Bitcoin-only
installation, you may omit the Litecoin and Bitcoin Cash Node components of the
path):
export PATH="$HOMEPATH/.local/bin:/mingw64/bin:$PATH:/c/Program Files/Bitcoin/daemon:/c/Program Files/Litecoin/daemon:/c/Program Files/Bitcoin-Cash-Node/daemon"
export PYTHONUTF8=1
```bash
export PATH="$HOMEPATH/.local/bin:/mingw64/bin:$PATH:/c/Program Files/Bitcoin/daemon:/c/Program Files/Litecoin/daemon:/c/Program Files/Bitcoin-Cash-Node/daemon"
export PYTHONUTF8=1
```
Save and exit. Close and reopen the terminal window to update your working
environment.
@ -233,11 +256,15 @@ environment.
On your online machine:
$ pip3 download ecdsa
```text
$ pip3 download ecdsa
```
Copy the downloaded file to your offline machine and install:
$ pip3 install --user ecdsa-*.whl
```text
$ pip3 install --user ecdsa-*.whl
```
### <a id="a_sc">7. Install the standalone scrypt package (required for strong password hashing)</a>
@ -248,59 +275,77 @@ therefore highly recommended.
On your online machine, download the tar archive:
$ pip3 download --no-deps scrypt==0.8.20
```text
$ pip3 download --no-deps scrypt==0.8.20
```
On your offline machine, unpack and enter the archive:
$ tar fax scrypt-0.8.20.tar.gz
$ cd scrypt-0.8.20
```text
$ tar fax scrypt-0.8.20.tar.gz
$ cd scrypt-0.8.20
```
Open the file `setup.py` in your text editor. Right before the line reading:
elif sys.platform.startswith('win32'):
```python
elif sys.platform.startswith('win32'):
```
insert the following lines, carefully preserving indentation:
elif os.environ.get('MSYSTEM') == 'MSYS':
define_macros = []
includes = ['/mingw64/include']
libraries = ['libcrypto']
CFLAGS.append('-O2')
```python
elif os.environ.get('MSYSTEM') == 'MSYS':
define_macros = []
includes = ['/mingw64/include']
libraries = ['libcrypto']
CFLAGS.append('-O2')
```
Save the file and exit the editor. Now build and install:
$ python3 setup.py install --user
```text
$ python3 setup.py install --user
```
### <a id="a_se">8. Clone and copy the secp256k1 library (offline install only)</a>
On your online machine, clone the secp256k1 repository from Github:
$ git clone https://github.com/bitcoin-core/secp256k1.git
```text
$ git clone https://github.com/bitcoin-core/secp256k1.git
```
On your offline machine, create a magic location and copy the cloned secp256k1
directory into it:
$ mkdir -p ~/.cache/mmgen
$ cp -a /path/to/secp256k1/repo/secp256k1 ~/.cache/mmgen
$ ls ~/.cache/mmgen/secp256k1/autogen.sh # check that the location is correct
```text
$ mkdir -p ~/.cache/mmgen
$ cp -a /path/to/secp256k1/repo/secp256k1 ~/.cache/mmgen
$ ls ~/.cache/mmgen/secp256k1/autogen.sh # check that the location is correct
```
### <a id="a_mm">9. Install MMGen</a>
Now you’re ready to install MMGen itself. On your online machine, clone the
repository:
$ git clone https://github.com/mmgen/mmgen
Cloning into ’mmgen’...
```text
$ git clone https://github.com/mmgen/mmgen
Cloning into ’mmgen’...
```
If you’re doing an offline install, then copy the cloned mmgen directory to
your offline machine.
Enter the repo directory, build and install:
$ cd mmgen
$ git checkout stable_msys2 # See 'Note' below
$ python3 -m build --no-isolation
$ python3 -m pip install --user --upgrade dist/*.whl
```text
$ cd mmgen
$ git checkout stable_msys2 # See 'Note' below
$ python3 -m build --no-isolation
$ python3 -m pip install --user --upgrade dist/*.whl
```
**Note:** if you want to use features that have appeared since the latest
`stable_msys2` release, then you can omit the `git checkout stable_msys2`
@ -321,16 +366,22 @@ wiki page for details.
If you’ll be using MMGen with Ethereum, then you must install a few
dependencies. From the MMGen repository root, type the following:
$ pip3 install --no-deps --user -r eth-requirements.txt
```text
$ pip3 install --no-deps --user -r eth-requirements.txt
```
For an offline install, do this instead:
$ pip3 download --no-deps -r eth-requirements.txt
```text
$ pip3 download --no-deps -r eth-requirements.txt
```
Then transfer the downloaded files to your offline machine, `cd` to the
directory containing the files and install them as follows:
$ pip3 install --no-deps --user *.whl
```text
$ pip3 install --no-deps --user *.whl
```
### <a id="a_cd">11. Install and launch your coin daemons</a>
@ -396,13 +447,15 @@ currently installed version of MMGen by issuing the command `mmgen-tool
To perform the upgrade, enter the MMGen repository root on your online
computer and issue the following commands:
$ git checkout master
$ git pull
$ git checkout stable_msys2 # See 'Note' to step 9
$ rm -rf dist build
$ rm -r /mingw64/lib/python*/site-packages/{mmgen,MMGen}*
$ python3 -m build --no-isolation
$ python3 -m pip install --upgrade dist/*.whl
```text
$ git checkout master
$ git pull
$ git checkout stable_msys2 # See 'Note' to step 9
$ rm -rf dist build
$ rm -r /mingw64/lib/python*/site-packages/{mmgen,MMGen}*
$ python3 -m build --no-isolation
$ python3 -m pip install --upgrade dist/*.whl
```
To update your offline installation, copy the updated repository (after `git
pull`) to your offline machine, `cd` to the root of the copied repository and

@ -6,7 +6,9 @@ binaries can be obtained [here][00] or [here][01].
After installation, locate the bitcoind executable, place it on your execution
path and start it with the command:
$ bitcoind -daemon -maxconnections=0
```text
$ bitcoind -daemon -maxconnections=0
```
Note that in the absence of a blockchain the daemon starts very quickly and
uses practically no CPU once running. Thus a low-powered computer such as a

@ -19,9 +19,11 @@ well as addresses, thus functioning as a hot wallet for a range of addresses.
Assuming your hot address range begins at 1001, you could start by creating a
key-address file for a hundred hot addresses like this:
$ mmgen-keygen --type=segwit 1001-1100
...
Secret keys written to file '89ABCDEF-S[1001-1100].akeys.mmenc'
```text
$ mmgen-keygen --type=segwit 1001-1100
...
Secret keys written to file '89ABCDEF-S[1001-1100].akeys.mmenc'
```
`mmgen-keygen` prompts you for a password to encrypt the key-address file with.
This is a wise precaution, as it provides at least some security for keys that
@ -30,14 +32,18 @@ will be stored on an online machine.
Now copy the key-address file to your online machine and import the addresses
into your tracking wallet:
$ mmgen-addrimport --batch --keyaddr-file '89ABCDEF-S[1001-1100].akeys.mmenc'
```text
$ mmgen-addrimport --batch --keyaddr-file '89ABCDEF-S[1001-1100].akeys.mmenc'
```
After funding your hot wallet by spending into some addresses in this range you
can do quickie transactions with these funds using the `mmgen-txdo` command:
$ mmgen-txdo -M '89ABCDEF-S[1001-1100].akeys.mmenc' 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 89ABCDEF:S:1010
...
Transaction sent: dcea1357....
```text
$ mmgen-txdo -M '89ABCDEF-S[1001-1100].akeys.mmenc' 1AmkUxrfy5dMrfmeYwTxLxfIswUCcpeysc,0.1 89ABCDEF:S:1010
...
Transaction sent: dcea1357....
```
The `--mmgen-keys-from-file` or `-M` option is required when using a key-address
file in place of a wallet. Note that your change address `89ABCDEF:S:1010` is

@ -12,27 +12,35 @@ This tutorial provides a quick, hands-on introduction.
1. Initialize MMGen regtest mode and start the regtest daemon:
$ mmgen-regtest setup
$ mmgen-regtest start
```text
$ mmgen-regtest setup
$ mmgen-regtest start
```
2. Generate Bob’s MMGen wallet:
$ mmgen-walletgen --bob
...
Make this wallet your default and move it to the data directory? (Y/n): y
```text
$ mmgen-walletgen --bob
...
Make this wallet your default and move it to the data directory? (Y/n): y
```
3. Generate three type `C` (compressed) addresses with Bob’s MMGen wallet:
$ mmgen-addrgen --bob --type=compressed 1-3
...
Addresses written to file '1163DDF1-C[1-3].addrs'
# 1163DDF1 is Bob’s Seed ID; since it’s generated randomly, yours will be different
```text
$ mmgen-addrgen --bob --type=compressed 1-3
...
Addresses written to file '1163DDF1-C[1-3].addrs'
# 1163DDF1 is Bob’s Seed ID; since it’s generated randomly, yours will be different
```
4. Import the addresses into Bob’s tracking wallet:
$ mmgen-addrimport --bob 1163DDF1-C[1-3].addrs
...
Type uppercase 'YES' to confirm: YES
```text
$ mmgen-addrimport --bob 1163DDF1-C[1-3].addrs
...
Type uppercase 'YES' to confirm: YES
```
Since your Bob has a different Seed ID, your address filename will of course
be different than this one.
@ -40,63 +48,79 @@ This tutorial provides a quick, hands-on introduction.
5. List the addresses in Bob’s tracking wallet. You’ll see the addresses you
just imported:
$ mmgen-tool --bob listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 0
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 0
1163DDF1:C:3 mhYYHM7renPpNi8SUj5yeEZ54eAUJ5HyQ1 - 0
```text
$ mmgen-tool --bob listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 0
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 0
1163DDF1:C:3 mhYYHM7renPpNi8SUj5yeEZ54eAUJ5HyQ1 - 0
```
Note that regtest mode uses testnet-format addresses, which differ from the
familiar mainnet addresses beginning with ’1’.
6. Fund one of the addresses (let’s choose the first one) with some BTC:
$ mmgen-regtest send mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ 500
```text
$ mmgen-regtest send mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ 500
```
Don’t forget to substitute your `C:1` address for the one above!
7. Make sure the funds reached their destination:
$ mmgen-tool --bob listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 500
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 0
1163DDF1:C:3 mhYYHM7renPpNi8SUj5yeEZ54eAUJ5HyQ1 - 0
TOTAL: 500 BTC
```text
$ mmgen-tool --bob listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 500
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 0
1163DDF1:C:3 mhYYHM7renPpNi8SUj5yeEZ54eAUJ5HyQ1 - 0
TOTAL: 500 BTC
```
8. You can view Bob’s total balance this way too:
$ mmgen-tool --bob getbalance
```text
$ mmgen-tool --bob getbalance
```
9. Generate Alice’s MMGen wallet:
$ mmgen-walletgen --alice
...
Make this wallet your default and move it to the data directory? (Y/n): y
```text
$ mmgen-walletgen --alice
...
Make this wallet your default and move it to the data directory? (Y/n): y
```
10. Generate three type `S` (segwit) addresses with Alice’s MMGen wallet:
$ mmgen-addrgen --alice --type=segwit 1-3
...
Addresses written to file '9304C211-S[1-3].addrs'
```text
$ mmgen-addrgen --alice --type=segwit 1-3
...
Addresses written to file '9304C211-S[1-3].addrs'
```
11. Repeat steps 4-7 for Alice by substituting `--bob` for `--alice`. Don’t
forget to change the address filename and send address to suit. The result of
step 7 will look something like this:
MMGenID ADDRESS COMMENT BALANCE
9304C211:S:1 2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu - 500
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 0
9304C211:S:3 2NF4y3y4CEjQCcssjX2BDLHT88XHn8z53JS - 0
TOTAL: 500 BTC
```text
MMGenID ADDRESS COMMENT BALANCE
9304C211:S:1 2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu - 500
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 0
9304C211:S:3 2NF4y3y4CEjQCcssjX2BDLHT88XHn8z53JS - 0
TOTAL: 500 BTC
```
12. Split Alice’s funds, sending 200 BTC to address `S:2` and the change to
`S:3`. Specify a fee of 20 satoshis/byte and make the output quieter:
$ mmgen-txdo --alice --tx-fee=20s --quiet 9304C211:S:2,300 9304C211:S:3
...
Type uppercase 'YES' to confirm: YES
Transaction sent: 78ca853816b55527b42ca8784c887a5f482c752522f914d2f17d6afcd8a3b076
```text
$ mmgen-txdo --alice --tx-fee=20s --quiet 9304C211:S:2,300 9304C211:S:3
...
Type uppercase 'YES' to confirm: YES
Transaction sent: 78ca853816b55527b42ca8784c887a5f482c752522f914d2f17d6afcd8a3b076
```
Don’t forget to use your Alice’s Seed ID here, instead of `9304C211`.
@ -108,34 +132,44 @@ step 7 will look something like this:
13. View the transaction in the mempool:
$ mmgen-regtest mempool
['78ca853816b55527b42ca8784c887a5f482c752522f914d2f17d6afcd8a3b076']
```text
$ mmgen-regtest mempool
['78ca853816b55527b42ca8784c887a5f482c752522f914d2f17d6afcd8a3b076']
```
14. Mine a block:
$ mmgen-regtest generate
```text
$ mmgen-regtest generate
```
15. Check the mempool again:
$ mmgen-regtest mempool
[]
```text
$ mmgen-regtest mempool
[]
```
16. List Alice’s addresses. Note that Alice has lost a bit to transaction fees:
$ mmgen-tool --alice listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
9304C211:S:1 2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu - 0
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 300
9304C211:S:3 2NF4y3y4CEjQCcssjX2BDLHT88XHn8z53JS - 199.999967
TOTAL: 499.999967 BTC
```text
$ mmgen-tool --alice listaddresses showempty=1
MMGenID ADDRESS COMMENT BALANCE
9304C211:S:1 2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu - 0
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 300
9304C211:S:3 2NF4y3y4CEjQCcssjX2BDLHT88XHn8z53JS - 199.999967
TOTAL: 499.999967 BTC
```
17. Have Alice send 10 BTC to Bob’s `C:2` address and the change back to her
`S:1` address. This time Alice specifies an absolute fee in BTC.
$ mmgen-txdo --alice --tx-fee=0.0001 --quiet 9304C211:S:1 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf,10
...
Enter a range or space-separated list of outputs to spend: 1
...
```text
$ mmgen-txdo --alice --tx-fee=0.0001 --quiet 9304C211:S:1 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf,10
...
Enter a range or space-separated list of outputs to spend: 1
...
```
Note that Alice is reusing address `S:1` here, and address reuse is
generally a bad idea. You’d be better off generating and importing some
@ -144,38 +178,50 @@ step 7 will look something like this:
18. Mine a block:
$ mmgen-regtest generate
```text
$ mmgen-regtest generate
```
19. List Alice’s addresses, omitting the empty ones:
$ mmgen-tool --alice listaddresses
MMGenID ADDRESS COMMENT BALANCE
9304C211:S:1 2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu - 189.999867
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 300
TOTAL: 489.999867 BTC
```text
$ mmgen-tool --alice listaddresses
MMGenID ADDRESS COMMENT BALANCE
9304C211:S:1 2N3HhxasbRvrJyHg72JNVCCPi9EUGrEbFnu - 189.999867
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 300
TOTAL: 489.999867 BTC
```
19. List Bob’s addresses:
$ mmgen-tool --bob listaddresses
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 500
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 10
TOTAL: 510 BTC
```text
$ mmgen-tool --bob listaddresses
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 500
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 10
TOTAL: 510 BTC
```
20. Add a label to Bob’s tracking wallet:
$ mmgen-tool --bob add_label 1163DDF1:C:2 'From Alice'
```text
$ mmgen-tool --bob add_label 1163DDF1:C:2 'From Alice'
```
21. List Bob’s addresses:
$ mmgen-tool --bob listaddresses
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 500
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf From Alice 10
TOTAL: 510 BTC
```text
$ mmgen-tool --bob listaddresses
MMGenID ADDRESS COMMENT BALANCE
1163DDF1:C:1 mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ - 500
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf From Alice 10
TOTAL: 510 BTC
```
22. When you’re finished, stop the regtest daemon:
$ mmgen-regtest stop
```text
$ mmgen-regtest stop
```
[G]: Getting-Started-with-MMGen#a_ct

@ -1,13 +1,13 @@
## Table of Contents
* [Introduction](#a_i)
* [Obtaining the binary seed](#a_rs)
* [Convert the seed to binary (legacy uncompressed addresses)](#a_ss)
* [Scramble the seed and save to binary (non-legacy and altcoin addresses and passwords)](#a_cs)
* [Convert the seed to binary (legacy uncompressed addresses)](#a_ss)
* [Scramble the seed and save to binary (non-legacy and altcoin addresses and passwords)](#a_cs)
* [Generating the keys](#a_gk)
* [Checking the result (optional, address example)](#a_cr)
* [Checking the result (optional, address example)](#a_cr)
* [Converting the hex value to a password (password example)](#a_hpw)
* [Hex to WIF by hand (address example)](#a_hw)
* [Base-conversion utility](#a_bcu)
* [Base-conversion utility](#a_bcu)
* [Converting an MMGen mnemonic to hexadecimal format](#a_mh)
#### <a id="a_i">Introduction</a>
@ -39,20 +39,24 @@ Okay, so let’s say you have a 128-bit seed with Seed ID `FE3C6545` and funds i
the first three legacy uncompressed (`L`) addresses of this seed. Here are the
addresses:
FE3C6545 {
1 1JVi3qcNcjMM7cTR7y9ihKUG1yDLpKRJfL
2 15EfKymfe3v7mqCaL174hTWSgBLFAHvtaR
3 1CUDd6nPHdP5pT7nN8k2AA5WdKRaKPjmea
}
```text
FE3C6545 {
1 1JVi3qcNcjMM7cTR7y9ihKUG1yDLpKRJfL
2 15EfKymfe3v7mqCaL174hTWSgBLFAHvtaR
3 1CUDd6nPHdP5pT7nN8k2AA5WdKRaKPjmea
}
```
Since you might have your funds in Segwit (`S`) addresses, we’ll consider that
case too:
FE3C6545 SEGWIT {
1 3LpkKqtGkcCukRrgEFWyCajSApioiEWeTw
2 3FYZQyWqBJcCjaSjCV9ZVj3gKyB9u8AYCX
3 37wM8hwt69qwH7hZHAMn6RVdc8vMuM1CwJ
}
```text
FE3C6545 SEGWIT {
1 3LpkKqtGkcCukRrgEFWyCajSApioiEWeTw
2 3FYZQyWqBJcCjaSjCV9ZVj3gKyB9u8AYCX
3 37wM8hwt69qwH7hZHAMn6RVdc8vMuM1CwJ
}
```
Keys for compressed (`C`), Bech32 (`B`) and altcoin addresses, as well as
passwords, are generated in a way analogous to Segwit keys, so for them you’ll
@ -61,7 +65,9 @@ proceed as with the Segwit case.
Here’s the seed itself in `mmhex` format, which you’ve stored in some safe place
(on paper in a safe-deposit box, for example):
afc3fe 456d 7f5f 1c4b fe3b c916 b875 60ae 6a3e
```text
afc3fe 456d 7f5f 1c4b fe3b c916 b875 60ae 6a3e
```
Now your task is to generate keys for the addresses so you can spend your coins.
This task is divided into two parts:
@ -80,7 +86,9 @@ storing it in a file. For that we use `xxd`, a handy tool for converting binary
to hex and vice versa. Don’t forget to omit the checksum from the seed and
remove the spaces:
$ echo 456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > myseed.bin
```bash
$ echo 456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > myseed.bin
```
#### <a id="a_cs">Scramble the seed and save to binary (non-legacy and altcoin addresses and passwords)</a>
@ -126,20 +134,25 @@ Once we’ve determined the correct string, we scramble our seed with it as
follows using the `openssl` utility available by default on any Unix-based
system:
# E.g. for LTC Segwit addresses:
$ scramble_str='ltc:segwit'
```bash
# e.g. for LTC Segwit addresses:
$ scramble_str='ltc:segwit'
# E.g. for default-format passwords for Alice’s email account at fubar.io:
$ scramble_str='b58:20:alice@fubar.io'
# e.g. for default-format passwords for Alice’s email account at fubar.io:
$ scramble_str='b58:20:alice@fubar.io'
$ echo -n "$scramble_str" | openssl dgst -r -sha256 -mac hmac -macopt hexkey:456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > scrambled-round0.bin
$ echo -n "$scramble_str" | openssl dgst -r -sha256 -mac hmac -macopt hexkey:456d7f5f1c4bfe3bc916b87560ae6a3e | xxd -r -p > scrambled-round0.bin
```
Now add the ten rounds of sha256:
$ for i in 0 1 2 3 4 5 6 7 8 9; do
openssl dgst -sha256 -binary scrambled-round${i}.bin > scrambled-round$((i+1)).bin
done
$ mv scrambled-round10.bin myseed.bin
```bash
$ for i in 0 1 2 3 4 5 6 7 8 9; do
openssl dgst -sha256 -binary scrambled-round${i}.bin > scrambled-round$((i+1)).bin
done
$ mv scrambled-round10.bin myseed.bin
```
#### <a id="a_gk">Generating the keys</a>
@ -148,38 +161,52 @@ SHA-256 branches to generate the keys from which each address is derived. To
obtain the chain’s first link, we make a single SHA-512 hash of the seed and
save it in binary form:
$ sha512sum myseed.bin | xxd -r -p > link1.bin
```bash
$ sha512sum myseed.bin | xxd -r -p > link1.bin
```
A double SHA-256 hash of the first link gives us the key of our first address:
$ sha256sum link1.bin | xxd -r -p | sha256sum
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
```bash
$ sha256sum link1.bin | xxd -r -p | sha256sum
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
```
# or, for the Segwit example:
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0
Or, for the Segwit example:
# or, for the password example:
bd60b8ba034bbb40498667ee600bc0cc0b99eb19164e8d412a48f16da4e00d6b
```text
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0
```
Or, for the password example:
```text
bd60b8ba034bbb40498667ee600bc0cc0b99eb19164e8d412a48f16da4e00d6b
```
#### <a id="a_cr">Checking the result (optional, address example)</a>
With `mmgen-tool`, we can easily generate the WIF key and address from this
hexadecimal key and see that it’s correct:
$ mmgen-tool hex2wif 05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
```bash
$ mmgen-tool hex2wif 05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
$ mmgen-tool wif2addr 5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
1JVi3qcNcjMM7cTR7y9ihKUG1yDLpKRJfL # matches FE3C6545:L:1 above
$ mmgen-tool wif2addr 5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
1JVi3qcNcjMM7cTR7y9ihKUG1yDLpKRJfL # matches FE3C6545:L:1 above
```
Or, for the Segwit example:
$ mmgen-tool hex2wif b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 compressed=1
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
```bash
$ mmgen-tool hex2wif b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 compressed=1
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
# for a compressed (`C`) address, leave out the `segwit=1` argument
$ mmgen-tool wif2addr L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F segwit=1
3LpkKqtGkcCukRrgEFWyCajSApioiEWeTw # matches FE3C6545:S:1 above
# for a compressed (`C`) address, leave out the `segwit=1` argument
$ mmgen-tool wif2addr L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F segwit=1
3LpkKqtGkcCukRrgEFWyCajSApioiEWeTw # matches FE3C6545:S:1 above
```
But since we’re trying to do this without the MMGen software, we need to find
some other way to do the hex-to-WIF conversion. We could use one of many
@ -192,11 +219,14 @@ passwords). To get the next key, we generate the next link in the chain from
the first link and take its double SHA-256 hash, just as we did for the first
one:
$ sha512sum link1.bin | xxd -r -p > link2.bin
$ sha256sum link2.bin | xxd -r -p | sha256sum
5db8fe3c8b52ccc98deab5afae780b6fbe56629e7ee1c6ed826fc2d6a81fb144 # uncompressed example
42f1b998f0f9b7b27b5d0b92ffa8c1c6b96d7202789c41b6e6a6a402e318a04d # Segwit example
9b59cec2e5d4f2a74f0d4eb2400efcf854f5a893bef0e9bf1ee83f72ca1118c3 # password example
```bash
$ sha512sum link1.bin | xxd -r -p > link2.bin
$ sha256sum link2.bin | xxd -r -p | sha256sum
5db8fe3c8b52ccc98deab5afae780b6fbe56629e7ee1c6ed826fc2d6a81fb144 # uncompressed example
42f1b998f0f9b7b27b5d0b92ffa8c1c6b96d7202789c41b6e6a6a402e318a04d # Segwit example
9b59cec2e5d4f2a74f0d4eb2400efcf854f5a893bef0e9bf1ee83f72ca1118c3 # password example
```
And so on and so forth, until we’ve generated all the keys we need: three, in our case.
@ -209,13 +239,17 @@ If it’s passwords we’re generating, we must now convert our hex key to the
desired password format, base58 in our case. For this we can use the homemade
`hex2b58.py` [Base-conversion utility](#a_bcu) described below:
# bd60b8... is the double sha256 of our link1.bin from above
$ ./hex2b58.py bd60b8ba034bbb40498667ee600bc0cc0b99eb19164e8d412a48f16da4e00d6b
DkFbZk2fDKQ7C55ASHQjhwcCdTsCiRq4ZLMMD5WQVAvv
```bash
# bd60b8... is the double sha256 of our link1.bin from above
$ ./hex2b58.py bd60b8ba034bbb40498667ee600bc0cc0b99eb19164e8d412a48f16da4e00d6b
DkFbZk2fDKQ7C55ASHQjhwcCdTsCiRq4ZLMMD5WQVAvv
```
The password is just the last 20 characters of the output:
dTsCiRq4ZLMMD5WQVAvv
```text
dTsCiRq4ZLMMD5WQVAvv
```
#### <a id="a_hw">Hex to WIF by hand (address example)</a>
@ -223,47 +257,65 @@ Since we’ve chosen to convert our hex keys to WIF format manually, we have a b
of work ahead of us. Let’s begin with our just-generated key #1 from seed
`FE3C6545`:
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36 (uncompressed example)
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 (Segwit example)
```bash
# uncompressed example
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
# Segwit example
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0
```
WIF format prepends hex `80` to the beginning of the key. If the key is
associated with a compressed public key, it also appends `01`:
# uncompressed example:
8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
```bash
# uncompressed example:
8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36
# Segwit example (Segwit uses compressed public keys):
80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a001
# Segwit example (Segwit uses compressed public keys):
80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a001
```
The Base58Check format invented by Satoshi for Bitcoin addresses and keys
contains a checksum, which we now generate by taking the first four bytes (eight
characters) of the double SHA256 of the above result:
# uncompressed example:
$ echo 8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36 | xxd -r -p | sha256sum | xxd -r -p | sha256sum | cut -c 1-8
7b818629
```bash
# uncompressed example:
$ echo 8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36 | xxd -r -p | sha256sum | xxd -r -p | sha256sum | cut -c 1-8
7b818629
# Segwit example:
$ echo 80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a001 | xxd -r -p | sha256sum | xxd -r -p | sha256sum | cut -c 1-8
89bba812
# Segwit example:
$ echo 80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a001 | xxd -r -p | sha256sum | xxd -r -p | sha256sum | cut -c 1-8
89bba812
```
The checksum gets appended to the end, giving us the following final result:
8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e367b818629 (uncompressed example)
80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812 (Segwit example)
```bash
# uncompressed example
8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e367b818629
# Segwit example
80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812
```
The last step is to convert all this into Base 58. Satoshi created Base-58
encoding for convenient and error-free writing down and dictating of Bitcoin
keys and addresses. He began with a Base-62 alphabet consisting of the ten
digits plus the upper and lower case Latin letters (10 + 26 + 26 = 62):
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlkmnopqrstuvwxyz
```text
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijlkmnopqrstuvwxyz
```
Since ‘0’ (zero) is easily confused with capital ‘O’ visually, and capital ‘I’
with lowercase ‘l’, he dropped those characters, leaving the following 58:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
```text
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
```
With ‘0’ gone, ‘1’ now represents decimal zero, ‘2’ represents decimal one, and
so forth all the way up to ‘z’, representing decimal fifty-seven.
@ -272,19 +324,21 @@ Now all that remains is to convert our hexadecimal key to decimal and then Base
58 using this alphabet. This can be done in just four lines of code you can try
out at the Python prompt:
# uncompressed example:
$ python3
>>> b58a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
>>> num = int('8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e367b818629',16)
>>> result = [b58a[num // 58**e % 58] for e in range(60)]
>>> print(''.join(reversed(result)).lstrip('1'))
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi # matches key for FE3C6545:L:1 above
```python
# uncompressed example:
$ python3
>>> b58a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
>>> num = int('8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e367b818629',16)
>>> result = [b58a[num // 58**e % 58] for e in range(60)]
>>> print(''.join(reversed(result)).lstrip('1'))
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi # matches key for FE3C6545:L:1 above
# Segwit example has the following differences:
...
>>> num = int('80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812',16)
...
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F # matches key for FE3C6545:S:1 above
# Segwit example has the following differences:
...
>>> num = int('80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812',16)
...
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F # matches key for FE3C6545:S:1 above
```
Explanation: the variable `b58a` holds the Base 58 alphabet; `num` holds the key
in decimal, converted from hexadecimal by Python’s `int()` function; the third
@ -295,40 +349,48 @@ the leading zeroes (‘1’s).
Programmers unfamiliar with Python might find the following base conversion code
clearer:
def numtob58(n):
result = []
while n:
result = result + [b58a[n % 58]] # divide n by 58 and take the remainder
n = n // 58
return result
```python
def numtob58(n):
result = []
while n:
result = result + [b58a[n % 58]] # divide n by 58 and take the remainder
n = n // 58
return result
result = numtob58(num)
result = numtob58(num)
```
#### <a id="a_bcu">Base-conversion utility</a>
Adapting our code a bit and putting it in a file gives us have a handy
conversion utility we can use for any key:
$ cat hex2b58.py
#!/usr/bin/env python3
import sys
b58a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
num = int(sys.argv[1],16)
result = [b58a[num // 58**e % 58] for e in range(60)]
print(''.join(reversed(result)).lstrip('1'))
```python
$ cat hex2b58.py
#!/usr/bin/env python3
import sys
b58a = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
num = int(sys.argv[1],16)
result = [b58a[num // 58**e % 58] for e in range(60)]
print(''.join(reversed(result)).lstrip('1'))
```
$ ./hex2b58.py 8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e367b818629
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
```text
$ ./hex2b58.py 8005d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e367b818629
5HrrmMdQbELyW7iCns5kvSbN9GCPTqEfG7iP1PZiYk49yDDivTi
$ ./hex2b58.py 80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
$ ./hex2b58.py 80b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a00189bba812
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
```
#### <a id="a_mh">Converting an MMGen mnemonic to hexadecimal format</a>
Our familiar base-10 system uses a series of ten symbols known as digits to
represent numbers from zero to nine:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
```text
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
```
If a number has more than one digit, its value is the sum of its digits
multiplied by increasing powers of ten, beginning with the rightmost, least
@ -336,27 +398,35 @@ significant digit (the “ones column”).
Thus the number 1234, for example, can be represented as follows:
4 x 1 +
3 x 10 +
2 x 100 +
1 x 1000
```text
4 x 1 +
3 x 10 +
2 x 100 +
1 x 1000
```
Or in exponential notation:
4 x 10⁰ +
3 x 10¹ +
2 x 10² +
1 x 10³
```text
4 x 10⁰ +
3 x 10¹ +
2 x 10² +
1 x 10³
```
An MMGen seed mnemonic is a number too, only the “digits” it’s comprised of come
from an alphabetically sorted series of 1626 words, the [Electrum wordlist][03],
which begins like this:
able (0), about (1), above (2), abuse (3), accept (4) ...
```text
able (0), about (1), above (2), abuse (3), accept (4) ...
```
and ends like this:
yet (1621), young (1622), yours (1623), yourself (1624), youth (1625)
```text
yet (1621), young (1622), yours (1623), yourself (1624), youth (1625)
```
(Type `mmgen-tool mn_printlist enum=true` to see the full enumerated list)
@ -365,60 +435,70 @@ just like the ten digits of our familiar base-10 system.
Here’s the mnemonic of our seed `FE3C6545`:
dude foot desperate tie stood themselves trip descend cease suicide apple busy
```text
dude foot desperate tie stood themselves trip descend cease suicide apple busy
```
To decode it, we begin by listing its words, from least to most significant,
along with the value of each word corresponding to its position in the wordlist:
busy - 200
apple - 59
suicide - 1384
cease - 221
descend - 379
trip - 1493
themselves - 1433
stood - 1348
tie - 1459
desperate - 386
foot - 562
dude - 439
```text
busy - 200
apple - 59
suicide - 1384
cease - 221
descend - 379
trip - 1493
themselves - 1433
stood - 1348
tie - 1459
desperate - 386
foot - 562
dude - 439
```
All that remains is to multiply the values by increasing powers of the base and
sum the results, just as we did in our ‘1234’ example above:
200 x 1626⁰ +
59 x 1626¹ +
1384 x 1626² +
221 x 1626³ +
379 x 1626⁴ +
1493 x 1626⁵ +
1433 x 1626⁶ +
1348 x 1626⁷ +
1459 x 1626⁸ +
386 x 1626⁹ +
562 x 1626¹⁰ +
439 x 1626¹¹
```text
200 x 1626⁰ +
59 x 1626¹ +
1384 x 1626² +
221 x 1626³ +
379 x 1626⁴ +
1493 x 1626⁵ +
1433 x 1626⁶ +
1348 x 1626⁷ +
1459 x 1626⁸ +
386 x 1626⁹ +
562 x 1626¹⁰ +
439 x 1626¹¹
```
While we could theoretically do the math with a calculator, a few lines of
Python will make our work much easier:
$ python3
>>> sum = exp = 0
>>> for word in (200,59,1384,221,379,1493,1433,1348,1459,386,562,439):
>>> sum += word * 1626 ** exp
>>> exp += 1
>>> print(hex(sum))
0x456d7f5f1c4bfe3bc916b87560ae6a3e # the result in hexadecimal: matches our original hex seed above
```python
$ python3
>>> sum = exp = 0
>>> for word in (200,59,1384,221,379,1493,1433,1348,1459,386,562,439):
>>> sum += word * 1626 ** exp
>>> exp += 1
>>> print(hex(sum))
0x456d7f5f1c4bfe3bc916b87560ae6a3e # the result in hexadecimal: matches our original hex seed above
```
In case you’re wondering why 1626 was chosen as the base: 1626 is just large
enough to allow a 128-bit seed to be represented by twelve words. This can also
be demonstrated at the Python prompt:
$ python3
>>> 1626**12 >= 2**128
True
>>> 1625**12 >= 2**128
False
```python
$ python3
>>> 1626**12 >= 2**128
True
>>> 1625**12 >= 2**128
False
```
[01]: https://github.com/casascius/Bitcoin-Address-Utility
[02]: https://github.com/matja/bitcoin-tool

@ -24,42 +24,50 @@ may be used.
If you have a default wallet installed, you may view the Seed IDs of its
subwallets like this:
$ mmgen-tool list_subseeds 1-5
Parent Seed: DF449DA4 (256 bits)
```text
$ mmgen-tool list_subseeds 1-5
Parent Seed: DF449DA4 (256 bits)
Long Subseeds Short Subseeds
------------- --------------
1L: FC9A8735 1S: 930E1AD5
2L: 62B02F54 2S: DF14AB49
3L: 9E884E99 3S: AD3ABD98
4L: DB595AE1 4S: 3E885EC4
5L: 36D5A0D1 5S: 30D66FF5
Long Subseeds Short Subseeds
------------- --------------
1L: FC9A8735 1S: 930E1AD5
2L: 62B02F54 2S: DF14AB49
3L: 9E884E99 3S: AD3ABD98
4L: DB595AE1 4S: 3E885EC4
5L: 36D5A0D1 5S: 30D66FF5
```
Here a range of 1-5 was chosen. Indexes of up to one million are allowed, which
means every wallet has a total of two million potential subwallets.
Subwallets may be referenced either by their Subseed Index or Seed ID:
$ mmgen-tool get_subseed 4S
3E885EC4
```text
$ mmgen-tool get_subseed 4S
3E885EC4
$ mmgen-tool get_subseed_by_seed_id 3E885EC4
4S
$ mmgen-tool get_subseed_by_seed_id 3E885EC4
4S
```
### Subwallet generation
To generate a subwallet, use the `mmgen-subwalletgen` command. For example,
you’d generate your default wallet’s 4th short subwallet as follows:
$ mmgen-subwalletgen 4S
...
MMGen wallet written to file '3E885EC4-ABCDEF00[128,3].mmdat'
```text
$ mmgen-subwalletgen 4S
...
MMGen wallet written to file '3E885EC4-ABCDEF00[128,3].mmdat'
```
And view its seed phrase like this:
$ mmgen-walletconv -qS -o words 3E885EC4-ABCDEF00[128,3].mmdat
...
peaceful marry wrong surround treasure sort use favorite enough wolf suspend path
```text
$ mmgen-walletconv -qS -o words 3E885EC4-ABCDEF00[128,3].mmdat
...
peaceful marry wrong surround treasure sort use favorite enough wolf suspend path
```
Since wallets generated by `mmgen-subwalletgen` are just ordinary wallets, you
can use them anywhere you’d use an ordinary MMGen wallet.
@ -86,39 +94,49 @@ A parent wallet may be used to generate keys and addresses for its associated
subwallets. Given our above example (a default wallet having subwallet `4S` with
Seed ID `3E885EC4`), the following two commands are equivalent:
# Generate ten bech32 addresses from the subwallet:
$ mmgen-addrgen --type=bech32 3E885EC4-ABCDEF00[128,3].mmdat 1-10
```text
# Generate ten bech32 addresses from the subwallet:
$ mmgen-addrgen --type=bech32 3E885EC4-ABCDEF00[128,3].mmdat 1-10
# Do the same thing, but using the parent wallet:
$ mmgen-addrgen --type=bech32 --subwallet=4S 1-10
# Do the same thing, but using the parent wallet:
$ mmgen-addrgen --type=bech32 --subwallet=4S 1-10
```
The same goes for transaction signing. Consider a transaction that spends to
and from addresses in the subwallet:
$ mmgen-txcreate 3E885EC4:B:2
(choose an input from subwallet 3E885EC4)
Transaction written to file '<something>.rawtx'
```text
$ mmgen-txcreate 3E885EC4:B:2
(choose an input from subwallet 3E885EC4)
Transaction written to file '<something>.rawtx'
```
This transaction can now be signed either with the subwallet itself:
$ mmgen-txsign *.rawtx 3E885EC4-ABCDEF00[128,3].mmdat
...
Signed transaction written to file '<something>.sigtx'
```text
$ mmgen-txsign *.rawtx 3E885EC4-ABCDEF00[128,3].mmdat
...
Signed transaction written to file '<something>.sigtx'
```
Or with its parent wallet:
$ mmgen-txsign *.rawtx
...
Found subseed 3E885EC4 (DF449DA4:4S)
...
Signed transaction written to file '<something>.sigtx'
```text
$ mmgen-txsign *.rawtx
...
Found subseed 3E885EC4 (DF449DA4:4S)
...
Signed transaction written to file '<something>.sigtx'
```
The latter command works “by magic” because by default each wallet scans its
first 100 subwallets for Seed IDs. For a transaction containing addresses from
a subwallet with an index higher than 100, say 144, we must extend the parent
wallet’s search like this:
$ mmgen-txsign --subseeds=144 *.rawtx
```text
$ mmgen-txsign --subseeds=144 *.rawtx
```
This is basically all you need to know about subwallets. For live versions of
the above examples that can be run as-is, see commits [`7538a94`][c1],

@ -22,44 +22,60 @@ The test suite requires the `/dev/loopX` devices to exist and be enabled. If
you’re running in an LXC container, note that only privileged containers allow
loop devices. You may enable them in the config file as follows:
lxc.cgroup2.devices.allow = b 7:0 rwm # /dev/loop0
lxc.cgroup2.devices.allow = b 7:1 rwm # /dev/loop1
lxc.cgroup2.devices.allow = b 7:2 rwm # /dev/loop2
```text
lxc.cgroup2.devices.allow = b 7:0 rwm # /dev/loop0
lxc.cgroup2.devices.allow = b 7:1 rwm # /dev/loop1
lxc.cgroup2.devices.allow = b 7:2 rwm # /dev/loop2
```
Every time the container is started, you may need to create the files afresh:
# mknod /dev/loop0 b 7 0
# mknod /dev/loop1 b 7 1
# mknod /dev/loop2 b 7 2
```text
# mknod /dev/loop0 b 7 0
# mknod /dev/loop1 b 7 1
# mknod /dev/loop2 b 7 2
```
### BTC-only testing
Clone the Bitcoin Core repo somewhere on your system:
$ git clone https://github.com/bitcoin/bitcoin
```text
$ git clone https://github.com/bitcoin/bitcoin
```
Install the Bitcoin Core daemon [(source)][sd] [(binaries)][bd].
Point the test suite to your copy of the Bitcoin Core repo:
$ export CORE_REPO_ROOT=/path/to/bitcoin/core/repo
```text
$ export CORE_REPO_ROOT=/path/to/bitcoin/core/repo
```
Install Pycoin:
$ python3 -m pip install --user pycoin
```text
$ python3 -m pip install --user pycoin
```
CD to the MMGen repository root and build without installing:
$ cd path/to/mmgen/repo
$ python3 setup.py build_ext --inplace
```text
$ cd path/to/mmgen/repo
$ python3 setup.py build_ext --inplace
```
Run the following if upgrading from a previous version of MMGen:
$ test/test.py clean
```text
$ test/test.py clean
```
Run the test suite in fast mode, skipping altcoin tests:
$ test/test-release.sh -F noalt
```text
$ test/test-release.sh -F noalt
```
### Complete testing (BTC plus all supported altcoins)
@ -84,52 +100,66 @@ steps:
Open PowerShell as administrator, and at the DOS prompt, execute:
system32> net user administrator /active:yes
system32> C:\\msys64\usr\bin\bash.exe --login
```text
system32> net user administrator /active:yes
system32> C:\\msys64\usr\bin\bash.exe --login
```
Now, at the MSYS2 prompt, cd to the MMGen repository root and run the setup
script:
$ scripts/msys2-sshd-setup.sh
```text
$ scripts/msys2-sshd-setup.sh
```
The daemon should now start automatically every time the system is booted. It
may also be started and stopped manually at the DOS or MSYS2 prompt as follows
(PowerShell must be running with admin privileges):
# net start msys2_sshd
# net stop msys2_sshd
```text
# net start msys2_sshd
# net stop msys2_sshd
```
#### Monero-Python
$ python3 -m pip install --user pycryptodomex ipaddress varint
$ python3 -m pip install --user --no-deps monero
```text
$ python3 -m pip install --user pycryptodomex ipaddress varint
$ python3 -m pip install --user --no-deps monero
```
#### Vanitygen PlusPlus (forked from Vanitygen Plus)
$ git clone https://github.com/10gic/vanitygen-plusplus
$ cd vanitygen-plusplus
$ git checkout -b vanitygen-plus e7858035d092 # rewind to fork commit
$ make keyconv # ‘mingw32-make.exe keyconv’ for MSYS2
$ sudo install --strip keyconv /usr/local/bin # ‘keyconv.exe’ for MSYS2
$ cd ..
```text
$ git clone https://github.com/10gic/vanitygen-plusplus
$ cd vanitygen-plusplus
$ git checkout -b vanitygen-plus e7858035d092 # rewind to fork commit
$ make keyconv # ‘mingw32-make.exe keyconv’ for MSYS2
$ sudo install --strip keyconv /usr/local/bin # ‘keyconv.exe’ for MSYS2
$ cd ..
```
#### Zcash-Mini
$ sudo apt-get install golang # skip this if Go is already installed
$ git clone https://github.com/FiloSottile/zcash-mini
$ cd zcash-mini
$ go mod init zcash-mini
$ go mod tidy
$ go build -mod=mod # or just ’go build’
$ sudo install --strip ./zcash-mini /usr/local/bin
$ cd ..
```text
$ sudo apt-get install golang # skip this if Go is already installed
$ git clone https://github.com/FiloSottile/zcash-mini
$ cd zcash-mini
$ go mod init zcash-mini
$ go mod tidy
$ go build -mod=mod # or just ’go build’
$ sudo install --strip ./zcash-mini /usr/local/bin
$ cd ..
```
#### Ethkey
On Arch Linux and ArchLinuxArm systems, the ‘ethkey’ utility is included in the
OpenEthereum package:
$ pacman -S openethereum
```text
$ pacman -S openethereum
```
For 64-bit Windows and Linux systems, ‘ethkey’ can be found in the zip archives
distributed with [this release][oz].
@ -146,7 +176,9 @@ If you experience such a failure, just restart the test.
Now you can run the test suite for all coins:
$ test/test-release.sh -F
```text
$ test/test-release.sh -F
```
## Overview of the individual tests

@ -6,68 +6,76 @@ call signatures.
### Initialize:
from mmgen.tool.api import tool_api
tool = tool_api()
```python
from mmgen.tool.api import tool_api
tool = tool_api()
```
### Key/address generation:
# List available coins:
print(' '.join(tool.coins))
```python
# List available coins:
print(' '.join(tool.coins))
# Initialize a coin/network pair:
proto = tool.init_coin('btc','mainnet')
# Initialize a coin/network pair:
proto = tool.init_coin('btc','mainnet')
# Print the available address types for current coin/network, along with a
# description. If tool.addrtype is unset, the first-listed will be used:
tool.print_addrtypes()
# Print the available address types for current coin/network, along with a
# description. If tool.addrtype is unset, the first-listed will be used:
tool.print_addrtypes()
# Set the address type to P2PKH with compressed public key:
tool.addrtype = 'compressed'
# Set the address type to P2PKH with compressed public key:
tool.addrtype = 'compressed'
# Skip user entropy gathering (not recommended)
tool.usr_randchars = 0
# Skip user entropy gathering (not recommended)
tool.usr_randchars = 0
# Generate a random hex secret:
hexsec = tool.randhex()
# Generate a random hex secret:
hexsec = tool.randhex()
# Generate the key and address:
wif = tool.hex2wif(hexsec)
addr = tool.wif2addr(wif)
# Generate the key and address:
wif = tool.hex2wif(hexsec)
addr = tool.wif2addr(wif)
# Generate an LTC regtest Segwit key and address:
proto = tool.init_coin('ltc','regtest')
tool.addrtype = 'segwit'
wif = tool.hex2wif(hexsec)
addr = tool.wif2addr(wif)
# Generate an LTC regtest Segwit key and address:
proto = tool.init_coin('ltc','regtest')
tool.addrtype = 'segwit'
wif = tool.hex2wif(hexsec)
addr = tool.wif2addr(wif)
# Generate a random LTC regtest Bech32 key/address pair:
tool.addrtype = 'bech32'
wif,addr = tool.randpair()
# Generate a random LTC regtest Bech32 key/address pair:
tool.addrtype = 'bech32'
wif,addr = tool.randpair()
```
### Mnemonic seed phrase generation:
# Generate an MMGen native mnemonic seed phrase:
mmgen_seed = tool.hex2mn(hexsec)
```python
# Generate an MMGen native mnemonic seed phrase:
mmgen_seed = tool.hex2mn(hexsec)
# Generate a BIP39 mnemonic seed phrase:
bip39_seed = tool.hex2mn(hexsec,fmt='bip39')
# Generate a BIP39 mnemonic seed phrase:
bip39_seed = tool.hex2mn(hexsec,fmt='bip39')
```
### Utility methods:
# Reverse the hex string:
hexsec_rev = tool.hexreverse(hexsec)
```python
# Reverse the hex string:
hexsec_rev = tool.hexreverse(hexsec)
# Get the HASH160 of the value:
sec_hash160 = tool.hash160(hexsec)
# Get the HASH160 of the value:
sec_hash160 = tool.hash160(hexsec)
# Convert the value to base58 format:
sec_b58 = tool.hextob58(hexsec)
# Convert the value to base58 format:
sec_b58 = tool.hextob58(hexsec)
# Convert the value to base58 check format:
sec_b58chk = tool.hextob58chk(hexsec)
# Convert the value to base58 check format:
sec_b58chk = tool.hextob58chk(hexsec)
# Convert the byte specification '4G' to an integer:
four_g = tool.bytespec('4G')
# Convert the byte specification '4G' to an integer:
four_g = tool.bytespec('4G')
# Convert the byte specification '4GB' to an integer:
four_gb = tool.bytespec('4GB')
# Convert the byte specification '4GB' to an integer:
four_gb = tool.bytespec('4GB')
```

@ -9,7 +9,9 @@ been spent to your MMGen wallet.
Make a plain list of the addresses, one address per line, and import the list
into the tracking wallet:
$ mmgen-addrimport --rescan -l my_existing_addrs
```text
$ mmgen-addrimport --rescan -l my_existing_addrs
```
NOTE: The '--rescan' option forces a rescan of the entire block chain, which is
required for all addresses with existing balances. The rescanning process is
@ -25,7 +27,9 @@ need their corresponding private keys.
If the key or keys in question are in a bitcoind wallet ('wallet.dat'), you can
extract them to a keylist file using the 'bitcoin-cli dumpwallet' command:
$ bitcoin-cli dumpwallet my_secret.keys
```text
$ bitcoin-cli dumpwallet my_secret.keys
```
This will write the keylist file 'my_secret.keys' to your home directory (or
maybe to your Bitcoin data directory, results may vary). If you want it written
@ -46,13 +50,17 @@ After creating a transaction that spends from one of your ordinary Bitcoin
addresses, transfer the raw transaction file to your offline computer and sign
it with the keylist file:
$ mmgen-txsign -k my_secret.keys F9DCBA[6.6].rawtx
...
Signed transaction written to file 'F9DCBA[6.6].sigtx'
```text
$ mmgen-txsign -k my_secret.keys F9DCBA[6.6].rawtx
...
Signed transaction written to file 'F9DCBA[6.6].sigtx'
```
If your transaction also contains MMGen inputs, you’ll need to provide a wallet
for them too, listing it at the end of the command line, like this:
$ mmgen-txsign -k my_secret.keys F9DCBA[6.6].rawtx 89ABCDEF-76543210[256,3].mmdat
```text
$ mmgen-txsign -k my_secret.keys F9DCBA[6.6].rawtx 89ABCDEF-76543210[256,3].mmdat
```
That’s it! Your signed transaction is ready to broadcast.

@ -19,12 +19,18 @@ separated by `/`, not `\`. The root of the filesystem is `/`. Drive letter
Environmental variables may be viewed with the `env` command. Individual
variables may be viewed like this:
$ echo $PATH
```text
$ echo $PATH
```
and set like this:
$ PATH=$PATH:/home/<username>/bin
```text
$ PATH=$PATH:/home/<username>/bin
```
Sometimes variables must be exported to be visible to called programs:
$ export PATH
```text
$ export PATH
```

@ -246,37 +246,43 @@ Shares can be made from and exported to all supported MMGen wallet formats.
This means you can split a BIP39 seed phrase, for example, and output the share
back to BIP39 in one easy command:
# Create share 1 of a 2-way split of the provided BIP39 seed phrase:
$ mmgen-seedsplit -o bip39 sample.bip39 1:2
```text
# Create share 1 of a 2-way split of the provided BIP39 seed phrase:
$ mmgen-seedsplit -o bip39 sample.bip39 1:2
```
Each share of a split has a unique share ID. The share IDs are displayed by
`mmgen-seedsplit` so that the user may record them for later reference. They
may also be viewed with the `mmgen-tool list_shares` command:
# List the share IDs of a 2-way named split 'alice' of your default wallet:
$ mmgen-tool list_shares 2 id_str=alice
```bash
# List the share IDs of a 2-way named split 'alice' of your default wallet:
$ mmgen-tool list_shares 2 id_str=alice
Seed: 71CA5049 (256 bits)
Split Type: 2-of-2 (XOR)
ID String: alice
Seed: 71CA5049 (256 bits)
Split Type: 2-of-2 (XOR)
ID String: alice
Shares
------
1: D0BBD210
2: 25F0BD65
Shares
------
1: D0BBD210
2: 25F0BD65
```
# List the share IDs of a 3-way default split of provided BIP39 seed phrase:
$ mmgen-tool list_shares 3 wallet=sample.bip39
```bash
# List the share IDs of a 3-way default split of provided BIP39 seed phrase:
$ mmgen-tool list_shares 3 wallet=sample.bip39
Seed: 03BAE887 (128 bits)
Split Type: 3-of-3 (XOR)
ID String: default
Seed: 03BAE887 (128 bits)
Split Type: 3-of-3 (XOR)
ID String: default
Shares
------
1: 83B9AF74
2: 109485F4
3: 424522DC
Shares
------
1: 83B9AF74
2: 109485F4
3: 424522DC
```
Share IDs are handy for checking the correctness of shares when rejoining a
split. Let’s say you’ve decided to rejoin your 2-way split with Alice, whose
@ -294,8 +300,10 @@ First, each share must be converted to hexadecimal data. If your shares are in
BIP39 format, for example, there are command-line tools available to do this.
Then a single line of Python code is all that’s required to finish the job:
$ python3
>>> seed_hex = hex(int(share1_hex,16) ^ int(share2_hex,16)) # rejoin a 2-way split
```python
$ python3
>>> seed_hex = hex(int(share1_hex,16) ^ int(share2_hex,16)) # rejoin a 2-way split
```
(Note that the XOR operator in Python is `^`.)

@ -1,4 +0,0 @@
[**Forum**](https://bitcointalk.org/index.php?topic=567069.0) |
[Reddit](https://www.reddit.com/user/mmgen-py) |
[PGP Public Keys](MMGen-Signing-Keys) |
Donate (BTC,BCH): 15TLdmi5NYLdqmtCqczUs5pBPkJDXRs83w