quotes, apostrophes, backticks
parent
05ed2a7806
commit
407f6cb7a2
4 changed files with 97 additions and 95 deletions
|
|
@ -1,15 +1,15 @@
|
|||
#### Perform the following steps on both your online and offline computers:
|
||||
|
||||
> Install required Debian/Ubuntu packages:
|
||||
Install required Debian/Ubuntu packages:
|
||||
|
||||
$ sudo apt-get install autoconf git libgmp-dev libssl-dev libtool wipe
|
||||
$ sudo apt-get install python3-dev python3-ecdsa python3-pexpect python3-setuptools python3-cryptography python3-nacl python3-pip python3-gmpy2
|
||||
|
||||
> Using the [pip3][P] installer, install the Python scrypt library (optional for Python >= v3.6):
|
||||
Using the [pip3][P] installer, install the Python scrypt library (optional for Python >= v3.6):
|
||||
|
||||
$ sudo -H pip3 install scrypt
|
||||
|
||||
> Install the secp256k1 library:
|
||||
Install the secp256k1 library:
|
||||
|
||||
$ git clone https://github.com/bitcoin-core/secp256k1.git
|
||||
$ cd secp256k1
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
$ sudo ldconfig
|
||||
$ cd ..
|
||||
|
||||
> Install MMGen:
|
||||
Install MMGen:
|
||||
|
||||
$ git clone https://github.com/mmgen/mmgen.git
|
||||
$ cd mmgen
|
||||
|
|
@ -28,10 +28,10 @@
|
|||
$ sudo ./setup.py install
|
||||
$ cd ..
|
||||
|
||||
> Install the bitcoind daemon(s):
|
||||
Install the bitcoind daemon(s):
|
||||
|
||||
> To install prebuilt binaries, go [here][01]. To install from source, go
|
||||
> [here][02].
|
||||
To install prebuilt binaries, go [here][01]. To install from source, go
|
||||
[here][02].
|
||||
|
||||
#### *Note for offline machines:*
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
MMGen's regtest mode, also known as Bob and Alice mode, uses the Bitcoin
|
||||
daemon's regression test feature to create a virtual network of two users who
|
||||
MMGen’s regtest mode, also known as Bob and Alice mode, uses the Bitcoin
|
||||
daemon’s regression test feature to create a virtual network of two users who
|
||||
transact on a private blockchain.
|
||||
|
||||
All of MMGen's functionality is available in regtest mode, making it an ideal
|
||||
All of MMGen’s functionality is available in regtest mode, making it an ideal
|
||||
way to learn to use the MMGen wallet without risking real coins.
|
||||
|
||||
To send a transaction or perform any other operation as Bob or Alice, just add
|
||||
the '--bob' or '--alice' option to the relevant MMGen command. MMGen will start
|
||||
the `--bob` or `--alice` option to the relevant MMGen command. MMGen will start
|
||||
and stop the Bitcoin daemon automatically as needed.
|
||||
|
||||
This tutorial provides a quick, hands-on introduction.
|
||||
|
|
@ -16,20 +16,20 @@ This tutorial provides a quick, hands-on introduction.
|
|||
$ mmgen-regtest setup
|
||||
$ mmgen-regtest bob
|
||||
|
||||
2. Generate Bob's MMGen wallet:
|
||||
2. Generate Bob’s MMGen wallet:
|
||||
|
||||
$ 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:
|
||||
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
|
||||
# 1163DDF1 is Bob’s Seed ID; since it’s generated randomly, yours will be different
|
||||
|
||||
4. Import the addresses into Bob's tracking wallet:
|
||||
4. Import the addresses into Bob’s tracking wallet:
|
||||
|
||||
$ mmgen-addrimport --bob 1163DDF1-C[1-3].addrs
|
||||
...
|
||||
|
|
@ -38,7 +38,7 @@ This tutorial provides a quick, hands-on introduction.
|
|||
Since your Bob has a different Seed ID, your address filename will of course
|
||||
be different than this one.
|
||||
|
||||
5. List the addresses in Bob's tracking wallet. You'll see the addresses you
|
||||
5. List the addresses in Bob’s tracking wallet. You’ll see the addresses you
|
||||
just imported:
|
||||
|
||||
$ mmgen-tool --bob listaddresses showempty=1
|
||||
|
|
@ -48,13 +48,13 @@ just imported:
|
|||
1163DDF1:C:3 mhYYHM7renPpNi8SUj5yeEZ54eAUJ5HyQ1 - 0
|
||||
|
||||
Note that regtest mode uses testnet-format addresses, which differ from the
|
||||
familiar mainnet addresses beginning with '1'.
|
||||
familiar mainnet addresses beginning with ’1’.
|
||||
|
||||
6. Fund one of the addresses (let's choose the first one) with some BTC:
|
||||
6. Fund one of the addresses (let’s choose the first one) with some BTC:
|
||||
|
||||
$ mmgen-regtest send mw42oJ94yRA6ZUNSzmMpjZDR74JNyvqzzZ 500
|
||||
|
||||
Don't forget to substitute your C:1 address for the one above!
|
||||
Don’t forget to substitute your C:1 address for the one above!
|
||||
|
||||
7. Make sure the funds reached their destination:
|
||||
|
||||
|
|
@ -65,23 +65,23 @@ just imported:
|
|||
1163DDF1:C:3 mhYYHM7renPpNi8SUj5yeEZ54eAUJ5HyQ1 - 0
|
||||
TOTAL: 500 BTC
|
||||
|
||||
8. You can view Bob's total balance this way too:
|
||||
8. You can view Bob’s total balance this way too:
|
||||
|
||||
$ mmgen-tool --bob getbalance
|
||||
|
||||
9. Generate Alice's MMGen wallet:
|
||||
9. Generate Alice’s MMGen wallet:
|
||||
|
||||
$ 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:
|
||||
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'
|
||||
|
||||
11. Repeat steps 4-7 for Alice by substituting '--bob' for '--alice'. Don't
|
||||
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:
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ step 7 will look something like this:
|
|||
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.
|
||||
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 output quieter:
|
||||
|
||||
$ mmgen-txdo --alice --tx-fee=20s --quiet 9304C211:S:2,300 9304C211:S:3
|
||||
|
|
@ -99,12 +99,12 @@ Specify a fee of 20 satoshis/byte and make output quieter:
|
|||
Type uppercase 'YES' to confirm: YES
|
||||
Transaction sent: 78ca853816b55527b42ca8784c887a5f482c752522f914d2f17d6afcd8a3b076
|
||||
|
||||
Don't forget to use your Alice's Seed ID here, instead of '9304C211'.
|
||||
Don’t forget to use your Alice’s Seed ID here, instead of `9304C211`.
|
||||
|
||||
Note that for simplicity's sake this tutorial uses the `mmgen-txdo` command
|
||||
Note that for simplicity’s sake this tutorial uses the `mmgen-txdo` command
|
||||
to create, sign and send transactions in one operation. In normal, cold
|
||||
wallet mode, your seed will be held on a separate offline computer which
|
||||
you'll use to sign transactions using the `mmgen-txsign` command. This is
|
||||
you’ll use to sign transactions using the `mmgen-txsign` command. This is
|
||||
explained in detail in the Getting Started guide.
|
||||
|
||||
13. View the transaction in the mempool:
|
||||
|
|
@ -121,7 +121,7 @@ Specify a fee of 20 satoshis/byte and make output quieter:
|
|||
$ mmgen-regtest show_mempool
|
||||
[]
|
||||
|
||||
16. List Alice's addresses. Note that Alice has lost a bit to transaction fees:
|
||||
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
|
||||
|
|
@ -130,24 +130,24 @@ Specify a fee of 20 satoshis/byte and make output quieter:
|
|||
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.
|
||||
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
|
||||
...
|
||||
|
||||
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 new addresses for
|
||||
Alice by repeating steps 3 and 4 with a different address range. I'll leave
|
||||
that to you as an exercise.
|
||||
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
|
||||
new addresses for Alice by repeating steps 3 and 4 with a different address
|
||||
range. I’ll leave that to you as an exercise.
|
||||
|
||||
18. Mine a block:
|
||||
|
||||
$ mmgen-regtest generate
|
||||
|
||||
19. List Alice's addresses, omitting the empty ones:
|
||||
19. List Alice’s addresses, omitting the empty ones:
|
||||
|
||||
$ mmgen-tool --alice listaddresses
|
||||
MMGenID ADDRESS COMMENT BALANCE
|
||||
|
|
@ -155,7 +155,7 @@ address. This time Alice specifies an absolute fee in BTC.
|
|||
9304C211:S:2 2N8w8qTupvd9L9wLFbrn6UhdfF1gadDAmFD - 300
|
||||
TOTAL: 489.999867 BTC
|
||||
|
||||
19. List Bob's addresses:
|
||||
19. List Bob’s addresses:
|
||||
|
||||
$ mmgen-tool --bob listaddresses
|
||||
MMGenID ADDRESS COMMENT BALANCE
|
||||
|
|
@ -163,11 +163,11 @@ address. This time Alice specifies an absolute fee in BTC.
|
|||
1163DDF1:C:2 n1oszhfAyRrHi7qJupyzaWXTcpMQGsGJEf - 10
|
||||
TOTAL: 510 BTC
|
||||
|
||||
20. Add a label to Bob's tracking wallet:
|
||||
20. Add a label to Bob’s tracking wallet:
|
||||
|
||||
$ mmgen-tool --bob add_label 1163DDF1:C:2 'From Alice'
|
||||
|
||||
21. List Bob's addresses:
|
||||
21. List Bob’s addresses:
|
||||
|
||||
$ mmgen-tool --bob listaddresses
|
||||
MMGenID ADDRESS COMMENT BALANCE
|
||||
|
|
|
|||
|
|
@ -12,31 +12,31 @@
|
|||
|
||||
#### <a name='a_i'>Introduction</a>
|
||||
|
||||
If you're considering using MMGen and are a Bitcoiner with a normal, healthy
|
||||
If you’re considering using MMGen and are a Bitcoiner with a normal, healthy
|
||||
degree of paranoia, then the following question will probably come to mind:
|
||||
“What if I have funds in an MMGen wallet and I lose the software? How do I
|
||||
recover my coins?”
|
||||
|
||||
Let's take this scenario to its logical extreme and assume you've lost all
|
||||
backup copies of the software, MMGen's project page has disappeared from Github
|
||||
(or been hacked) and no other repositories or copies are available on the
|
||||
Internet. The following tutorial will show you how to recover the private keys
|
||||
for your coin addresses in the event this unlikely combination of circumstances
|
||||
ever occurs.
|
||||
Let’s take this scenario to its logical extreme and assume you’ve lost all
|
||||
backup copies of the software, MMGen’s project page has disappeared from both
|
||||
[Github][04] and [Gitlab][05] (or been hacked) and no other repositories or
|
||||
copies are available on the Internet. The following tutorial will show you how
|
||||
to recover the private keys for your coin addresses in the event this unlikely
|
||||
combination of circumstances ever occurs.
|
||||
|
||||
In addition to private keys, this tutorial can also be used to recover passwords
|
||||
generated with the `mmgen-passgen` command.
|
||||
|
||||
#### <a name='a_rs'>Obtaining the binary seed</a>
|
||||
|
||||
To keep things simple, we'll assume you have a copy of your seed in hexadecimal
|
||||
(mmhex) format. If your backup's in mnemonic format, skip to the section
|
||||
'Converting an MMGen mnemonic to hexadecimal format' below and return here when you've
|
||||
finished. If your backup is an MMGen wallet, it will need to be decrypted.
|
||||
That case will be covered in a future tutorial.
|
||||
To keep things simple, we’ll assume you have a copy of your seed in hexadecimal
|
||||
(mmhex) format. If your backup’s in mnemonic format, skip to the section
|
||||
’Converting an MMGen mnemonic to hexadecimal format’ below and return here when
|
||||
you’ve finished. If your backup is an MMGen wallet, it will need to be
|
||||
decrypted. That case will be covered in a future tutorial.
|
||||
|
||||
Okay, so let's say you have a 128-bit seed with Seed ID FE3C6545 and funds in
|
||||
the first three legacy uncompressed ('L') addresses of this seed. Here are the
|
||||
Okay, so let’s say you have a 128-bit seed with Seed ID `FE3C6545` and funds in
|
||||
the first three legacy uncompressed (`L`) addresses of this seed. Here are the
|
||||
addresses:
|
||||
|
||||
FE3C6545 {
|
||||
|
|
@ -45,7 +45,7 @@ addresses:
|
|||
3 1CUDd6nPHdP5pT7nN8k2AA5WdKRaKPjmea
|
||||
}
|
||||
|
||||
Since you might have your funds in Segwit ('S') addresses, we'll consider that
|
||||
Since you might have your funds in Segwit (`S`) addresses, we’ll consider that
|
||||
case too:
|
||||
|
||||
FE3C6545 SEGWIT {
|
||||
|
|
@ -54,12 +54,12 @@ case too:
|
|||
3 37wM8hwt69qwH7hZHAMn6RVdc8vMuM1CwJ
|
||||
}
|
||||
|
||||
Keys for compressed ('C'), Bech32 (‘B’) and altcoin addresses, as well as
|
||||
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
|
||||
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):
|
||||
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
|
||||
|
||||
|
|
@ -70,14 +70,14 @@ This task is divided into two parts:
|
|||
2. converting the hex keys to wallet interchange (WIF) format for importation
|
||||
into Bitcoin Core or some other wallet.
|
||||
|
||||
We'll solve this task using standard command-line utilities available on any
|
||||
We’ll solve this task using standard command-line utilities available on any
|
||||
Linux or other Unix-like system.
|
||||
|
||||
> #### <a name='a_ss'>Convert the seed to binary (legacy uncompressed addresses)</a>
|
||||
|
||||
> For the legacy addresses, we begin by converting the seed to binary form and
|
||||
> 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
|
||||
> 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
|
||||
|
|
@ -117,19 +117,19 @@ Linux or other Unix-like system.
|
|||
|
||||
> | Password type | Scramble String |
|
||||
> |:-----------------------------------------|:-------------------------|
|
||||
> | Base58 passwords for Alice's email acct. | `b58:20:alice@fubar.io` |
|
||||
> | Base58 passwords for Alice’s email acct. | `b58:20:alice@fubar.io` |
|
||||
> | Same as above, half-length passwords | `b58:10:alice@fubar.io` |
|
||||
> | Same as above, default Base32 passwords | `b32:24:alice@fubar.io` |
|
||||
> | 32-byte hex seed for Alice's PGP key | `hex:64:alice@gnupg` |
|
||||
> | 32-byte hex seed for Alice’s PGP key | `hex:64:alice@gnupg` |
|
||||
|
||||
> Once we've determined the correct string, we scramble our seed with it as
|
||||
> 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'
|
||||
|
||||
# E.g. for default-format passwords for Alice's email account at 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
|
||||
|
|
@ -145,7 +145,7 @@ Linux or other Unix-like system.
|
|||
|
||||
The MMGen key-generating algorithm uses a chain of SHA-512 hashes with double
|
||||
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
|
||||
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
|
||||
|
|
@ -163,8 +163,8 @@ A double SHA-256 hash of the first link gives us the key of our first address:
|
|||
|
||||
> #### <a name='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:
|
||||
> 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
|
||||
|
|
@ -177,17 +177,17 @@ A double SHA-256 hash of the first link gives us the key of our first address:
|
|||
$ mmgen-tool hex2wif b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 compressed=1
|
||||
L3R8Fn21PsY3PWgT8BMggFwXswA2EZntwEGFS5mfDJpSiLq29a9F
|
||||
|
||||
# for a compressed ('C') address, leave out the 'segwit=1' argument
|
||||
# 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
|
||||
> 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
|
||||
> key-manipulation tools available on the Internet, such as [this one][01], or
|
||||
> [this one][02]. Or we can do it ourselves: that will be covered in the next
|
||||
> section.
|
||||
|
||||
Meanwhile, let's finish generating hex keys for the rest of our addresses (or
|
||||
Meanwhile, let’s finish generating hex keys for the rest of our addresses (or
|
||||
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:
|
||||
|
|
@ -198,14 +198,14 @@ one:
|
|||
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.
|
||||
And so on and so forth, until we’ve generated all the keys we need: three, in our case.
|
||||
|
||||
If we're generating keys for Ethereum and Monero, our work is done: the raw
|
||||
If we’re generating keys for Ethereum and Monero, our work is done: the raw
|
||||
hexadecimal keys are all we need. Otherwise, read on.
|
||||
|
||||
#### <a name='a_hpw'>Converting the hex value to a password (password example)</a>
|
||||
|
||||
If it's passwords we're generating, we must now convert our hex key to the
|
||||
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:
|
||||
|
||||
|
|
@ -219,15 +219,15 @@ The password is just the last 20 characters of the output:
|
|||
|
||||
#### <a name='a_hw'>Hex to WIF by hand (address example)</a>
|
||||
|
||||
Since we've chosen to convert our hex keys to WIF format manually, we have a bit
|
||||
of work ahead of us. Let's begin with our just-generated key #1 from seed
|
||||
FE3C6545:
|
||||
Since we’ve chosen to convert our hex keys to WIF format manually, we have a bit
|
||||
of work ahead of us. Let’s begin with our just-generated key #1 from seed
|
||||
`FE3C6545`:
|
||||
|
||||
05d7219524b983290138a60ada101370007f59a625c43a46f0f8d92950955e36 (uncompressed example)
|
||||
b8e58ded53e9ba5a9f4e279a956c061a7da5487bde6a95f1ede0722d287881a0 (Segwit example)
|
||||
|
||||
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':
|
||||
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
|
||||
|
|
@ -237,7 +237,7 @@ associated with a compressed public key, it also appends '01':
|
|||
|
||||
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 SHA-256 of the above result:
|
||||
characters) of the double SHA256 of the above result:
|
||||
|
||||
|
||||
# uncompressed example:
|
||||
|
|
@ -260,13 +260,13 @@ digits plus the upper and lower case Latin letters (10 + 26 + 26 = 62):
|
|||
|
||||
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:
|
||||
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
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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
|
||||
|
|
@ -286,11 +286,11 @@ out at the Python prompt:
|
|||
...
|
||||
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 hexidecimal by Python's `int()` function; the third
|
||||
Explanation: the variable `b58a` holds the Base 58 alphabet; `num` holds the key
|
||||
in decimal, converted from hexidecimal by Python’s `int()` function; the third
|
||||
line does the base-58 conversion; and the last line formats the result by
|
||||
reversing the order of the digits, converting it to a string and stripping off
|
||||
the leading zeroes ('1's).
|
||||
the leading zeroes (‘1’s).
|
||||
|
||||
Programmers unfamiliar with Python might find the following base conversion code
|
||||
clearer:
|
||||
|
|
@ -298,7 +298,7 @@ clearer:
|
|||
def numtob58(n):
|
||||
result = []
|
||||
while n:
|
||||
result = result + [b58a[n % 58]] # divide 'n' by 58 and take the remainder
|
||||
result = result + [b58a[n % 58]] # divide n by 58 and take the remainder
|
||||
n = n / 58
|
||||
return result
|
||||
|
||||
|
|
@ -348,7 +348,7 @@ Or in exponential notation:
|
|||
2 x 10² +
|
||||
1 x 10³
|
||||
|
||||
An MMGen seed mnemonic is a number too, only the “digits” it's comprised of come
|
||||
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:
|
||||
|
||||
|
|
@ -363,7 +363,7 @@ and ends like this:
|
|||
The words of the Electrum wordlist thus make up a base-1626 numbering system,
|
||||
just like the ten digits of our familiar base-10 system.
|
||||
|
||||
Here's the mnemonic of our seed (FE3C6545):
|
||||
Here’s the mnemonic of our seed `FE3C6545`:
|
||||
|
||||
dude foot desperate tie stood themselves trip descend cease suicide apple busy
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ Python will make our work much easier:
|
|||
>>> print '{:x}'.format(sum)
|
||||
456d7f5f1c4bfe3bc916b87560ae6a3e # 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
|
||||
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:
|
||||
|
||||
|
|
@ -425,3 +425,5 @@ be demonstrated at the Python prompt:
|
|||
[01]: https://github.com/casascius/Bitcoin-Address-Utility
|
||||
[02]: https://github.com/matja/bitcoin-tool
|
||||
[03]: https://github.com/spesmilo/electrum/blob/1.9.5/lib/mnemonic.py
|
||||
[04]: https://github.com/mmgen/mmgen
|
||||
[05]: https://gitlab.com/mmgen/mmgen
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ from which it was derived.
|
|||
Subwallets are specified by a “Subseed Index” consisting of:
|
||||
|
||||
a) an integer in the range 1-1000000, plus
|
||||
b) an optional single letter, ‘L’ or ‘S’
|
||||
b) an optional single letter, `L` or `S`
|
||||
|
||||
The letter designates the length of the subwallet’s seed. If omitted, ‘L’ is
|
||||
The letter designates the length of the subwallet’s seed. If omitted, `L` is
|
||||
assumed.
|
||||
|
||||
Long (‘L’) subwallets have the same seed length as their parent wallet
|
||||
(typically 256 bits), while short (‘S’) subwallets always have 128-bit seeds.
|
||||
Long (`L`) subwallets have the same seed length as their parent wallet
|
||||
(typically 256 bits), while short (`S`) subwallets always have 128-bit seeds.
|
||||
Long and short subwallets for a given index are derived independently, so both
|
||||
may be used.
|
||||
|
||||
|
|
@ -83,8 +83,8 @@ to a single master wallet and derive all subwallets from this single parent.
|
|||
### Address generation and transaction signing using the parent wallet
|
||||
|
||||
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:
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue