This commit fixes two issues in the writeDirtyToDisk function:
First, closing the temporary files is now done using a defer, so they
are always closed.
Second, the various account mutexs are no longer unlocked using a
defer, preventing more than one from being held at once and causing a
deadlock caused by incorrect locking order.
Boolean options cannot be unset from a default true value on the
command line, so invert the allowfree option, renaming it
disallowfree, so attaching fees may always be forced by specifying
disallowfree = true in the configuration file, or --disallowfree on
the command line.
It may be desirable to never allow free transactions, even if the
calculated priority is high enough that a fee would not be required,
so this change adds a global configuration option to remove this check
and always attach a fee.
Now that it has been decided that all account wallets will share the
same passphrase, the walletlock and walletpassphrase RPC handlers now
go through the accountstore to lock or unlock all account wallets,
rather than only changing the default account.
This change checks for all wallet files in the account directory, and
then attempts to open each of the available accounts for those
wallets. Before, only the default account would ever be opened.
There were several places where various account files (wallet, tx, or
utxo stores) were being marked as dirty, and then not being either
immediately synced to disk or marked as a dirty account so they would
be scheduled to be synced to disk. This change adds Account functions
to mark as dirty and add the account to the map of scheduled accounts
so they won't be missed by the disk syncer goroutine.
This change allows for the use of watching-only wallets. Unlike
normal, "hot" wallets, watching-only wallets do not contain any
private keys, and can be used in situations where you want to keep one
wallet online to create new receiving addresses and watch for received
transactions, while keeping the hot wallet offline (possibly on an
air-gapped computer).
Two (websocket) extension RPC calls have been added:
First, exportwatchingwallet, which will export the current hot wallet
to a watching-only wallet, saving either to disk or returning the
base64-encoded wallet files to the caller.
Second, recoveraddresses, which is used to recover the next n
addresses from the address chain. This is used to "sync" a watching
wallet with the hot wallet, or vice versa.
This adds some missing bookkeeping which broke rescans for the root
addresses of newly created wallets (not wallets read from disk) by
marking all active addresses (which would be just the root address) as
belonging to the account with a some particular name.
While here, return an error to the caller rather than just logging the
error if the newly-created wallet cannot be immediatelly written to
disk.
The exported watching wallet would include all imported addresses'
chain indexes added to the chain index map. Imported addresses are
special as they do not belong to the address chain, and this would
cause issues when serializing the wallet.
This adds a new function, ExtendActiveAddresses, to extend the number
of active addresses, generated by the address chain, by any arbitrary
positive number. This will be used for recovering wallet addresses
from a wallet backup, as well as getting the next as many addresses as
required to keep a watching wallet in sync with an original wallet
with the private keys, or sync an original wallet with new addresses
generated by the watching wallet.
This change introduces a new function to export a wallet in memory to
a watching wallet. Watching wallets allow to watch for balance
changes and transactions to wallet addresses while only storing the
public parts of a wallet (no private keys). New addresses created by
the watching wallet will use pubkey address chaining and will allow to
receive funds to an indefinite number of new addresses, and create the
private keys for said addresses from the non-watching wallet later.
The actual exporting of a watching wallet to a file (triggered by an
RPC request) is not yet implemented.
While here, fix an issue found by new test code for the chained
address code which incorrectly set the starting index of addresses in
the chain needing private keys to be created.
Strings are immutable, so instead of copying as a new variable (like
how was needed when receiving byte slices), just pass the marshaled
JSON string to the notification processing code.
This change adds a check for a valid (32-byte length) secret before
attempting to encrypt or decrypt any addresses. If the check fails, a
meaningful error (ErrWalletLocked) is returned to the caller, rather
than an error out of the aes package.
This function was not implemented (returning zero values) and all
versioning is handled internally by the wallet's ReadFrom and WriteTo
functions. If the read wallet does not match the latest file version,
it is read in the old format, but always written back with the new
format.
The wallet package was using a sync.Mutex around the saved decryption
key (kept in memory for an unlocked wallet). As the wallet package is
designed to use no internal locking, and correct synchronization is
provided by the importers of the package, this mutex has been removed.
This change uses the ChainedPubKey function to create addresses from
the previous address's public key and the wallet chaincode, without
the need for the private key, if the keypool has been depleted and the
wallet is locked. This is done since the next chained private key is
unsolvable without a locked wallet.
If a wallet contains any of these chained addresses with missing
private keys, the private keys are created during the next wallet
unlock, using ChainedPrivKey.
This change adds a function to generate the next public key of the
address chain from the previous public key and chaincode, without
needing the previous address's private key. This will be used to
allow generating new addresses with an unlocked wallet, where the
private keys are created on the next unlock.
Tests have been added to verify that the chained private and private
keys match each other (using both chaining functions) as well as an
expected value in the test case. ECDSA signature creation and
verifiction is also performed using the generated keypairs to verify
the next keypair is valid.
btcwallet originally correctly copied the behavior of armory when
chaining new private keys off the previous private key, but this
regressed in commit e8265eca41 with a
switch from double sha256 to a single sha256.
This change reverts the behavior (using the clearly-named function
btcwire.DoubleSha256) to match armory's and old btcwallet's address
chaining algorithm.
If you have flipped the switch to use btcwallet on mainnet, any newly
generated addresses created for the keypool after Jan 6, 2014 (the
date the regression was committed) should be backed up with
dumpprivkey (using btcctl) and a new wallet backup should be made of
your current wallet file (~/.btcwallet/mainnet/wallet.bin on unix) to
avoid the possibility of losing any real money.
This change makes the disk syncer write all three files (wallet, tx,
and utxo) instead of just the wallet, which will result in warnings at
startup if the tx/utxo files cannot be found.
Fixes#30.
When disk syncing a wallet file, if the wallet is flagged dirty, the
disk syncer must grab the wallet writer lock to set dirty=false. The
disk syncing code was being called in the end of
(*Account).RescanActiveAddresses with the reader lock held (unlocked
using a defer), which prevented the writer lock from being aquired.
This change removes the defered unlock to release the reader lock
before syncing to disk.