Skip to content

Commit 5e4147d

Browse files
committed
more documentation
1 parent 1542cd5 commit 5e4147d

File tree

1 file changed

+68
-7
lines changed

1 file changed

+68
-7
lines changed

src/main/java/prof7bit/bitcoin/wallettool/fileformats/WalletDatHandler.xtend

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ class WalletDatHandler extends AbstractImportExportHandler {
108108
}
109109
}
110110

111+
/**
112+
* Parse a wallet.dat file and provide access
113+
* to its keys. This class can not be used to
114+
* write or create new wallets, its read-only.
115+
*/
111116
class WalletDat {
112117
val log = LoggerFactory.getLogger(this.class)
113118

@@ -130,6 +135,17 @@ class WalletDat {
130135
var int mkey_nDerivationIterations
131136
var String mkey_other_params
132137

138+
/**
139+
* Parse the file (or throw exception if unreadable).
140+
* If the constructor returns then this WalletDat
141+
* Object will hold collections of all parsed keys
142+
* that can be read with the public methods that
143+
* are provided for this purpose. It can only read
144+
* existing and not write. The method isEncrypted()
145+
* can be used to test whether it is encrypted and
146+
* the decrypt() method should be used to decrypt
147+
* all keys.
148+
*/
133149
new (File file) throws Exception {
134150
try {
135151
log.info("opening file {}", file)
@@ -240,6 +256,14 @@ class WalletDat {
240256
log.trace("found: type 'pool' n={}", n)
241257
}
242258

259+
/**
260+
* @return true if the wallet contains an encrypted
261+
* master-key which means all keys are encrypted.
262+
*/
263+
def isEncrypted(){
264+
mkey_encrypted_key != null
265+
}
266+
243267
private def readString(ByteBuffer buf) {
244268
new String(buf.readSizePrefixedByteArray)
245269
}
@@ -273,13 +297,20 @@ class WalletDat {
273297
}
274298
}
275299

276-
277300
/**
278-
* Decrypt (if encrypted) the keys in the raw key list,
279-
* do nothing if they are not encrypted
301+
* Decrypt (if encrypted) the keys in the raw key list.
302+
* If the wallet is not encrypted this does nothing.
303+
* After decryption succeeded the keys can be accessed
304+
* through the other methods, if it fails an exception
305+
* might be thrown. Because it is not guaranteed that
306+
* it will always throw when the password was wrong the
307+
* code that will later try to use the decrypted keys
308+
* must check that public and private keys actually make
309+
* sense and fit together (which the importer will do
310+
* anyways).
280311
*/
281312
def decrypt(String password) throws Exception {
282-
if (mkey_encrypted_key != null){
313+
if (encrypted){
283314
if (password == null){
284315
throw new FormatFoundNeedPasswordException
285316
}
@@ -311,7 +342,10 @@ class WalletDat {
311342
/**
312343
* Return the collection of all WalletDatRawKeyData objects.
313344
* This is used by the importer after the wallet has been
314-
* completely parsed and decrypted.
345+
* completely parsed and decrypted. They are not checked for
346+
* consistency or decryption errors, this must be done
347+
* separately by the application that uses them (must check
348+
* that private key and public key actually fit together)!
315349
*/
316350
def getKeys() {
317351
rawKeyList.keyData.values
@@ -400,6 +434,15 @@ class WalletDat {
400434
}
401435
}
402436

437+
/**
438+
* Abstract base class for all bdb pages. A Page is a block
439+
* of the file of fixed size, the entire file is made up of
440+
* such pages. There are several types of pages but all of
441+
* them share a minimum of information like page number,
442+
* next/previous page, page type, etc. This class does not
443+
* expose all these fields, only the bare minimum needed to
444+
* read through a b-tree file.
445+
*/
403446
abstract class BerkeleyDBPage {
404447
// page types
405448
static val P_LBTREE = 5 /* B-tree leaf. */
@@ -446,7 +489,13 @@ abstract class BerkeleyDBPage {
446489
}
447490

448491
/**
449-
* this is a leaf page, it contains all the data
492+
* this is a leaf page, it contains all the data. Data
493+
* is organized as key/value pairs. Each of them consists
494+
* of two entries, the page also contains a lookup table
495+
* to find the offsets of these data items to be able to
496+
* simply access them by index number. Even index numbers
497+
* are the key and the odd number directly following it is
498+
* its value. Its pretty simple actually.
450499
*/
451500
class BerkeleyDBLeafPage extends BerkeleyDBPage {
452501
static val SIZE_LEAF_HEADER = 26
@@ -529,7 +578,13 @@ class BerkeleyDBLeafPage extends BerkeleyDBPage {
529578
}
530579

531580
/**
532-
* this is only used for page 0 to read magic, version, page size, etc.
581+
* This is only used for page #0 to read magic, version,
582+
* page size, etc. Although we read only the first few
583+
* bytes it should be noted that this is also a complete
584+
* page, its just mostly empty. More similar meta data
585+
* pages might appear later in the file but we only care
586+
* about the first one right at the start of the file,
587+
* it contains all we need.
533588
*/
534589
class BerkeleyDBHeaderPage extends BerkeleyDBPage {
535590
static val SIZE_METADATA_HEADER = 72
@@ -660,6 +715,12 @@ class WalletDatRawKeyDataList {
660715
* and optionally decrypting the wallet this contains
661716
* all information about a key with the only exception
662717
* of label which is stored in a separate map.
718+
*
719+
* Note: during decryption there is no check performed
720+
* that public and private key actually fit together,
721+
* this must be checked by the application that is going
722+
* to use these keys. The WalletDatHandler import handler
723+
* will perform this check (its needed anyways).
663724
*/
664725
class WalletDatRawKeyData {
665726
public var byte[] encrypted_private_key

0 commit comments

Comments
 (0)