In this commit we add a set of benchmarks to be able to measure the
enciphering and deciphering speed of the current scheme with the
current scrypt parameters.
On my laptop I get about 100ms per attempt:
⛰ go test -run=XXX -bench=.
goos: darwin
goarch: amd64
pkg: github.com/lightningnetwork/lnd/aezeed
BenchmarkToMnenonic-4 10 102287840 ns/op
BenchmarkFromMnenonic-4 10 105874973 ns/op
PASS
ok github.com/lightningnetwork/lnd/aezeed 3.036s
In this commit, we add a new package implementing the aezeed cipher
seed scheme. This is a new scheme developed that aims to overcome the
two major short comings of BIP39: a lack of a version, and a lack of a
wallet birthday. A lack a version means that wallets may not
necessarily know *how* to re-derive addresses during the recovery
process. A lack of a birthday means that wallets don’t know how far
back to look in the chain to ensure that they derive *all* the proper
user addresses.
The aezeed scheme addresses these two drawbacks and adds a number of
desirable features. First, we start with the following plaintext seed:
{1 byte internal version || 2 byte timestamp || 16 bytes of entropy}.
The version field is for wallets to be able to know *how* to re-derive
the keys of the wallet.
The 2 byte timestamp is expressed in Bitcoin Days Genesis, meaning that
the number of days since the timestamp in Bitcoin’s genesis block. This
allow us to save space, and also avoid using a wasteful level of
granularity. With the currently, this can express time up until 2188.
Finally, the entropy is raw entropy that should be used to derive
wallet’s HD root.
Next, we’ll take the plaintext seed described above and encipher it to
procure a final cipher text. We’ll then take this cipher text (the
CipherSeed) and encode that using a 24-word mnemonic. The enciphering
process takes a user defined passphrase. If no passphrase is provided,
then the string “aezeed” will be used.
To encipher a plaintext seed (19 bytes) to arrive at an enciphered
cipher seed (33 bytes), we apply the following operations:
* First we take the external version an append it to our buffer. The
external version describes *how* we encipher. For the first version
(version 0), we’ll use scrypt(n=32768, r=8, p=1) and aezeed.
* Next, we’ll use scrypt (with the version 9 params) to generate a
strong key for encryption. We’ll generate a 32-byte key using 5 bytes
as a salt. The usage of the salt is meant to make the creation of
rainbow tables infeasible.
* Next, the enciphering process. We use aezeed, modern AEAD with
nonce-misuse resistance properties. The important trait we exploit is
that it’s an *arbitrary input length block cipher*. Additionally, it
has what’s essentially a configurable MAC size. In our scheme we’ll use
a value of 4, which acts as a 32-bit checksum. We’ll encrypt with our
generated seed, and use an AD of (version || salt). We'll them compute a
checksum over all the data, using crc-32, appending the result to the
end.
* Finally, we’ll encode this 33-byte cipher text using the default
world list of BIP 39 to produce 24 english words.
The `aezeed` cipher seed scheme has a few cool properties, notably:
* The mnemonic itself is a cipher text, meaning leaving it in
plaintext is advisable if the user also set a passphrase. This is in
contrast to BIP 39 where the mnemonic alone (without a passphrase) may
be sufficient to steal funds.
* A cipherseed can be modified to *change* the passphrase. This
means that if the users wants a stronger passphrase, they can decipher
(with the old passphrase), then encipher (with a new passphrase).
Compared to BIP 39, where if the users used a passphrase, since the
mapping is one way, they can’t change the passphrase of their existing
HD key chain.
* A cipher seed can be *upgraded*. Since we have an external version,
offline tools can be provided to decipher using the old params, and
encipher using the new params. In the future if we change ciphers,
change scrypt, or just the parameters of scrypt, then users can easily
upgrade their seed with an offline tool.
* We're able to verify that a user has input the incorrect passphrase,
and that the user has input the incorrect mnemonic independently.
In this commit, we fix a bug in the query routes RPC that could at
times lead to a panic. This would happen if the number of returned
routes was less than the number of expected routes. To remedy this,
we’ll return the minimum of the number of requested routes, and the
number of routes actually returned.
In this commit, we reduce the total number of allocations that a
brontide session will incur over its lifetime. Profiling on one of my
nodes showed that we were generating a lot of garbage due to
re-creating a 65KB buffer to read the next message each time the
ReadMessage method was called.
To reduce the total number of memory allocations, we’ll now simply
re-use a buffer for both the cipher text header, and the cipher text
itself.
In this commit, we modify our initial cert generation to *only* generate
and advertise cipher suites that purely use ECC. We do this is as
switching to ECC results in much faster startup time for a fresh
installation, and is also more modern crypto. # Please enter the commit
message for your changes. Lines starting
In this commit, we update glide to the latest version of btcwallet that
includes fixes for better fee estimation, and also fixes to ensure that
transaction broadcast is reliable across all current backend
implementations.
In this commit, we update the commit of my btcd fork as the saltiest
commit includes a fix for a breaking change (or bug fix). After this
commit, we’ll able to run the set of integration tests with golfing
1.10.
In this commit, we modify the edgeWeight function that’s used within
the findPath method to weight fees more heavily than the time lock
value at an edge. We do this in order to greedily prefer lower fees
during path finding. This is a simple stop gap in place of more complex
weighting parameters that will be investigated later.
We also modify the edge distance to use an int64 rather than a float.
Finally an additional test has been added in order to excessive this
new change. Before the commit, the test was failing as we preferred the
route with lower total time lock.
In this commit, we modify the caching structure to return a set of
cached routes for a request if the number of routes requested is less
than or equal to the number of cached of routes.
In this commit, we modify the findPaths method to take the max number
of routes to return. With this change, FindRoutes can eventually itself
also take a max number of routes in order to make the function useable
again.
In this commit, we made a series of modification to the way we handle
reading edges and vertexes from disk, in order to reduce the amount of
garbage generated:
1. Properly use PubKeyBytes are required rather than PubKey()
2. Return direct structs rather than pointers, and leave it to the
runtime to perform escape analysis.
3. In-line the former readSig() method when reading sigs from disk.
In this commit, we fix a lingering bug related to the way that we
deliver block epoch notifications to end users. Before this commit, we
would launch a new goroutine for *each block*. This was done in order
to ensure that the notification dispatch wouldn’t block the main
goroutine that was dispatching the notifications. This method archived
the goal, but had a nasty side effect that the goroutines could be
re-ordered during scheduling, meaning that in the case of fast
successive blocks, then notifications would be delivered out of order.
Receiving out of order notifications is either disallowed, or can cause
sub-systems that rely on these notifications to get into weird states.
In order to fix this issue, we’ll no longer launch a new goroutine to
deliver each notification to an awaiting client. Instead, each client
will now gain a concurrent in-order queue for notification delivery.
Due to the internal design of chainntnfs.ConcurrentQueue, the caller
should never block, yet the receivers will receive notifications in
order. This change solves the re-ordering issue and also minimizes the
number of goroutines that we’ll create in order to deliver block epoch
notifications.
In this commit, we modify our initialization of neutrino to also pass
in the custom dialer and name resolver function. With this change, if
lnd is configured to use Tor, then neutrino will as well. This means
that *both* the Bitcoin P2P as well as the Lightning P2P traffic will
be proxied over Tor.
In this commit, we extend the TorDial function and add a new attribute
to the TorProxyNet struct to allow the caller to opt for stream
isolation or not. Using stream isolation, we ensure that each new
connection uses a distinct circuit.
In this commit, we fix a regression introduced by a recent change which
would allow the agent to detect a channel as failed, and blacklist the
node, promising faster convergence with the ideal state of the
heuristic.
The source of this bug is that we would use the set of blacklisted
nodes in order to compute how many additional channels we should open.
If 10 failures happened, then we would think that we had opened up 10
channels, and stop much earlier than we actually should.
To fix this, while ensuring we don’t retry to failed peers, the
NeedMoreChans method will now return *how* anymore channels to open,
and the Select method will take in how many channels it should try to
open *exactly*.
In this commit, we update the chan closer state machine to be fully
spec compliant. A recent change was made to the spec to enforce a
strict ordering such that, the negotiation is well formed. To enact
this change, we’ll ensure that before the closeFeeNegotiation phase,
the *initiator* is always the one that sends the CloseSigned message
first.
In this commit, we fix a slight miscalculation within the GetInfo call.
Before this commit, we would list any channel that the peer knew of as
active, instead of those which are, well, actually *active*. We fix
this by skipping any channels that we don’t have the remote revocation
for.
In this commit, we make an API change that’s meant to reduce the amount
of garbage we generate when doing pathfinding or syncing nodes with our
latest graph state. Before this commit, we would always have to fully
decode the public key and signatures when reading a edge or vertex
struct. For the edges, we may need several EC operations to fully
decode all the pubkeys. This has been seen to generate a ton of
garbage, as well as slow down path finding a good bit.
To remedy this, we’ll now only ever read the *raw* bytes from disk. In
the event that we actually need to verify a signature (or w/e), only
*then* will we fully decode everything.
In this commit, we replace all instances of *btcec.PublicKey within the
announcement messages with a simple [33]byte. We do this as usually we
don’t need to immediately validate an announcement, therefore we can
avoid the scalar multiplications during decoding.
In this commit, we add a new signature type. We’ll use this type to
avoid fully decoding a signature on the wire into a btcec.Signature.
This type is only really needed when we need to do signature
validation, as a result, always encoding it is a waste. Several helper
methods have been added to the new struct in order to ensure that we
can use it in the existing codebase without substantial issues.
In this commit, we fix an existing grouting leak within the contract
court package. If a goroutine dies, but it doesn’t actually cancel the
block epoch notification that it requested, then it’s possible to leak
thousands of gorutines. To remedy this situation, we ensure that we’ll
*always* cancel the epoch notification once the goroutine has exited.
In this commit, we fix an existing bug that would result in some
payments getting “stuck”. This would happen if one side restarted
before the channel was fully locked in. In this case, since upon
re-connection, the link will get added to the switch with a *short
channel ID of zero*. If A then tries to make a multi-hop payment
through B, B will fail to forward the payment, as it’ll mistakenly
think that the payment originated from a local-subsystem as the channel
ID is zero. A short channel ID of zero is used to map local payments
back to their caller.
With fix this by allowing the funding manager to dynamically update the
short channel ID of a link after it discovers the short channel ID.
In this commit, we fix a second instance of reported “stuck” payments
by users.
In this commit, we fix an existing bug within the funding manager. A
channel barrier only needs to be create if upon startup the channel is
still pending. Otherwise, we’ll re-create the funding barrier
unnecessarily. This can lead to bugs when initiating payments between a
channels’ lock in and when it’s announced to the together network. If
during this period, a user attempts a payment, then the response won’t
be archived, as the grouting will be blocked waiting on the channel
barrier to close.
To fix this, we only re-create the barrier if the channel hasn’t been
confirmed.
This eliminates one source of reported “stuck payments”.
In this commit, we remove a server shutdown statement that was executed
after we obtained the wallet’s password from the user over RPC. This
was unnecessary as we already close the listener below. Before this
commit, users would see a weird benign error message. With these code
deletion, the message disappears.
In this commit, we fix an issue that was recently introduced to the way
we handle historical dispatches for the neutrino notifier. In a recent
change, we no return an error if we’re unable to actually find the
transaction that spends an outpoint. If this is the case, then the
outpoint is actually unspent, and we should proceed as normal.
Before this commit, if the remaining change was small enough, then it
was possible for us to generate a non-std funding transaction. This is
an issue as the txn would fail to propagate, meaning funds could
potentially be stuck in limbo if users didn't manually drop their
transaction history.
To avoid this scenario, we won't create a change output that is dusty.
Instead, we'll add these as miner fees.
Fixes#690.
In this commit, we modify the logic executed when we decide that we
need to fail a funding flow. Before this commit, if the remote party
disconnected while we were attempting to fail the funding flow with an
error. Then we'd never actually cancel the reservation. This meant that
any inputs selected for that transaction would be locked until a
restart.
We fix this issue by always cancelling the reservation first, and
ensuring that failure to cancel the reservation doesn't prevent us from
sending the error.
Partially addresses #710.
In this commit, we add an additional constraint to the RPC
configuration parsing. Before this commit, it was possible to start lnd
with either RPC server listening on an external interface *without*
authentication disabled. After this commit, if a user tries to start
the RPC server listening on an external interface without any sort of
RPC authentication, then the daemon will fail to start up.
In order to reduce high CPU utilization during the initial network view
sync, we slash down the total number of active in-flight jobs that can
be launched.
A recent commit modified the mutex in the server to the read/write. In
order to further reduce contention, we’ll grab the read lock when we’re
examining get set of peers to ignore.
Before this commit, we’d unnecessarily use a write transaction within
the FetchChannelEdgesByOutpoint. This is wasteful as the function only
actually reads items from the database, and doesn’t attempt any
mutations at all.
In this commit, we fix a race condition related to the way we attempt
to query to see if an outpoint has already been spent by the time it’s
registered within the ChainNotifier. If the transaction creating the
outpoint hasn’t made it into the mempool by the time we execute the
GetTxOut call, then we’ll attempt to query for the transaction itself.
In this case, if we query for the transaction, then the block hash
field will be empty as it hasn’t yet made it into a block. Under the
previous logic, we’d then attempt to force a rescan. This is an issue
as the forced rescan will fail since it’ll try to fetch the block hash
of all zeroes.
In this commit, we fix this issue by only entering this “fallback to
rescan” logic iff, the transaction has actually been mined.