use fencing for code blocks
parent
91ce23b994
commit
2e37167340
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],
|
||||
|
|
|
|||
104
Test-Suite.md
104
Test-Suite.md
|
|
@ -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
|
||||
|
||||
|
|
|
|||
92
Tool-API.md
92
Tool-API.md
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue