f5591f3c0f
In this commit we replace addUtxo with processTransaction in the wallet API. addUtxo is kept around, but only as an internal implementation detail. The new flow looks like this: 1) The wallet gets notified about a new TX through a processTransaction call 2) It then searches through our already processed incoming TXs: if found, updates the confirmation status else, inserts it into the DB 3) We then call addUtxo, if the previous step resulted in a new TX in our DB |
||
---|---|---|
.. | ||
src/main/scala/org/bitcoins/wallet | ||
README.md |
wallet
This is meant to be a stand alone project that can be used as a cold storage wallet and hot wallet.
Features
- utxo storage
- key storage
- key generation
- coin selection
- transaction building
- fee calculation
Design choices
- Private key material is just stored once, as the mnemonic code used to initialize the wallet
- Addresses we hand out to users are stored with their BIP44/BIP49/BIP84 paths and script types, so that everything we need for spending the money sent to an address is derivable.
- The wallet is a "dumb" wallet that acts mostly as a database of UTXOs, transactions and
addresses, with associated operations on these.
The wallet module does very little verification of incoming data about transactions,
UTXOs and reorgs. We're aiming to write small, self contained modules, that can be
composed together into more fully fledged systems. That means the
chain
andnode
modules does the actual verification of data we receive, andwallet
just blindly acts on this. This results in a design where you can swap outnode
for a Bitcoin Core full node, use it with hardware wallets, or something else entirely. However, that also means that users ofwallet
that doesn't want to use the other modules we provide have to make sure that the data they are feeding the wallet is correct.
Database structure
We store information in the following tables:
- UTXOs - must reference the incoming transaction it was received in
- Addresses - must reference the account it belongs to
- Accounts
- Incoming transactions - must reference the SPK (in our address table) that a TX spends to
- Outgoing transactions - must reference the UTXO(s) it spends
Mnemonic encryption
The mnemonic seed to the Bitcoin-S wallet is written to disk, encrypted. The file name is
$HOME/.bitcoin-s/$NETWORK/encrypted_bitcoin-s_seed.json
. We store it in a JSON object
that looks like this:
{
"iv": "initializationVector",
"cipherText": "encryptedCipherText",
"salt": "saltUsedInEncryption"
}
The parts that's relevant to this part of the wallet is WalletStorage.scala
(where we handle
the actual reading from and writing to disk), EncryptedMnemonic.scala
(where we convert an
encrypted mnemonic to a cleartext mnemonic) and AesCrypt.scala
(where do the actual
encryption/decryption).
We use AES encryption for this, block cipher mode and PKCS5 padding. The wallet password is fed
into the PBKDF2 key stretching function, using SHA512 as the HMAC function. This happens in
PBKDF2.scala
.