Matt Corallo [Fri, 5 Mar 2021 16:02:42 +0000 (11:02 -0500)]
Add assertions for in-order block [dis]connection in ChannelManager
Sadly the connected-in-order tests have to be skipped in our normal
test suite as many tests violate it. Luckily we can still enforce
it in the tests which run in other crates.
Jeffrey Czyz [Thu, 4 Mar 2021 02:33:54 +0000 (18:33 -0800)]
Correctly update the last block hash on disconnect
When a block is disconnected, the hash of the disconnected block was
used to update the last connected block. However, this amounts to a
no-op because these hashes should be equal. Successive disconnections
would update the hash but leave it one block off.
Normally, this not a problem because the last block_disconnected should
be followed by block_connected since the former is triggered by a chain
re-org. However, this assumes the user calls the API correctly and that
no failure occurs that would prevent block_connected from being called
(e.g., if fetching the connected block fails).
Instead, update the last block hash with the disconnected block's
previous block hash.
Jeffrey Czyz [Thu, 4 Mar 2021 03:21:16 +0000 (19:21 -0800)]
Order ChannelManager lock acquisition
Since last_block_hash is read while updating channels and written when
blocks are connected and disconnected, its lock should be held for the
duration of these operations. Further, since the channel_state lock is
already held during these operations, an ordering of lock acquisition
should be maintained to enforce consistency.
Ordering lock acquisition such that channel_state is held for the
duration of last_block_hash gives a consistent ordering.
Jeffrey Czyz [Fri, 5 Mar 2021 02:22:37 +0000 (18:22 -0800)]
Pass along ChannelManager's last_block_hash
ChannelMonitor keeps track of the last block connected. However, it is
initialized with the default block hash, which is a problem if the
ChannelMonitor is serialized before a block is connected. Instead, pass
ChannelManager's last_block_hash, which is initialized with a "birthday"
hash, when creating a new ChannelMonitor.
Jeffrey Czyz [Fri, 5 Mar 2021 01:39:21 +0000 (17:39 -0800)]
Remove last_block_connected from Channel
Tracking the last block was only used to de-duplicate block_connected
calls, but this is no longer required as of the previous commit.
Further, the ChannelManager can pass the latest block hash when needing
to create a ChannelMonitor rather than have each Channel maintain an
up-to-date copy. This is implemented in the next commit.
Jeffrey Czyz [Fri, 5 Mar 2021 00:58:26 +0000 (16:58 -0800)]
Remove block_connected de-duplication logic
Calling block_connected for the same block was necessary when clients
were expected to re-fetch filtered blocks with relevant transactions. At
the time, all listeners were notified of the connected block again for
re-scanning. Thus, de-duplication logic was put in place.
Jeffrey Czyz [Wed, 3 Mar 2021 19:24:55 +0000 (11:24 -0800)]
Parameterize ChannelManager::new with a block hash
When ChannelMonitors are persisted, they need to store the most recent
block hash seen. However, for newly created channels the default block
hash is used. If persisted before a block is connected, the funding
output may be missed when syncing after a restart. Instead, initialize
ChannelManager with a "birthday" hash so it can be used later when
creating channels.
Gleb Naumenko [Mon, 1 Mar 2021 10:37:51 +0000 (12:37 +0200)]
Don't underpay htlc_min due to path contribution
We could have possibly constructed a slightly inconsistent
path: since we reduce value being transferred all the way, we
could have violated htlc_minimum_msat on some channels
we already passed (assuming dest->source direction). Here,
we recompute the fees again, so that if that's the case, we
match the currently underpaid htlc_minimum_msat with fees.
Change ChannelManager deserialization to return an optional blockhash
If the ChannelManager never receives any blocks, it'll return a default blockhash
on deserialization. It's preferable for this to be an Option instead.
Jeffrey Czyz [Tue, 2 Mar 2021 18:03:11 +0000 (10:03 -0800)]
Add validate_best_block_header utility
Refactor synchronize_listeners by pulling out a function returning the
validated block header of a BlockSource's best chain tip. This is needed
when a node is started from scratch and has no listeners to sync.
Jeffrey Czyz [Mon, 1 Mar 2021 06:39:01 +0000 (22:39 -0800)]
Implement chain::Listen without using RefCell
The implementation of chain::Listen for ChannelMonitor required using a
RefCell since its block_connected method required a mutable borrow. This
is no longer the case since ChannelMonitor now uses interior mutability
via a Mutex. So the RefCell is no longer needed.
Jeffrey Czyz [Mon, 1 Mar 2021 06:26:41 +0000 (22:26 -0800)]
Change Mutex to RwLock in ChainMonitor
Now that ChannelMonitor uses an internal Mutex to support interior
mutability, ChainMonitor can use a RwLock to manage its ChannelMonitor
map. This allows parallelization of update_channel operations since an
exclusive lock only needs to be held when adding to the map in
watch_channel.
Jeffrey Czyz [Mon, 1 Mar 2021 05:42:27 +0000 (21:42 -0800)]
Move ChannelMonitor state behind a Mutex
ChainMonitor accesses a set of ChannelMonitors behind a single Mutex.
As a result, update_channel operations cannot be parallelized. It also
requires using a RefCell around a ChannelMonitor when implementing
chain::Listen.
Moving the Mutex into ChannelMonitor avoids these problems and aligns it
better with other interfaces. Note, however, that get_funding_txo and
get_outputs_to_watch now clone the underlying data rather than returning
references.
Matt Corallo [Mon, 1 Mar 2021 20:10:59 +0000 (15:10 -0500)]
Provide Dummy routing and channel message handlers for users
We currently "support" not having a router or channel in memory by
forcing users to implement the same, but its trivial to provide our
own dummy implementations.
Matt Corallo [Sat, 9 Jan 2021 02:55:47 +0000 (21:55 -0500)]
[bindings] Build a wasm32-wasi library in genbindings.sh
This will switch to use the clang/C WASM ABI instead of the
wasm_bindgen WASM ABI as of rustc 1.51 (or nightly since [1]),
allowing us to link C and Rust code in a single wasm binary.
Matt Corallo [Fri, 26 Feb 2021 23:16:14 +0000 (18:16 -0500)]
[bindings] Be explicit when calling trait methods in generated code
For ChannelManager, at least, we have two separate functions called
block_connected, one in the Listen trait, one in the struct, we
need to be explicit with which one we're trying to call.
Jeffrey Czyz [Fri, 5 Feb 2021 03:20:03 +0000 (19:20 -0800)]
Utility for syncing a set of chain listeners
Add a utility for syncing a set of chain listeners to a common chain
tip. Required to use before creating an SpvClient when the chain
listener used with the client is actually a set of listeners each of
which may have had left off at a different block. This would occur when
the listeners had been persisted individually at different frequencies
(e.g., a ChainMonitor's individual ChannelMonitors).
Jeffrey Czyz [Thu, 4 Feb 2021 01:41:03 +0000 (17:41 -0800)]
Add SpvClient used to poll for the best chain tip
Adds a lightweight client for polling one or more block sources for the
best chain tip. Notifies listeners of blocks connected or disconnected
since the last poll. Useful for keeping a Lightning node in sync with
the chain.
Jeffrey Czyz [Mon, 1 Feb 2021 21:17:20 +0000 (13:17 -0800)]
Add ChainNotifier and define ChainListener trait
Add an interface for being notified of block connected and disconnected
events, along with a notifier for generating such events. Used while
polling block sources for a new tip in order to feed these events into
ChannelManager and ChainMonitor.
Jeffrey Czyz [Mon, 1 Feb 2021 07:43:43 +0000 (23:43 -0800)]
Add ChainPoller implementation of Poll trait
ChainPoller defines a strategy for polling a single BlockSource. It
handles validating chain data returned from the BlockSource. Thus, other
implementations of Poll must be defined in terms of ChainPoller.
Jeffrey Czyz [Mon, 1 Feb 2021 07:42:27 +0000 (23:42 -0800)]
Define a Poll trait as an adaptor on BlockSource
SPV clients need to poll one or more block sources for the best chain
tip and to retrieve related chain data. The Poll trait serves as an
adaptor interface for BlockSource. Implementations may define an
appropriate polling strategy.
Add support for `opt_shutdown_anysegwit` feature #780
* Implemented protocol.
* Made feature optional.
* Verify that the default value is true.
* Verify that on shutdown,
if Channel.supports_shutdown_anysegwit is enabled,
the script can be a witness program.
* Added a test that verifies that a scriptpubkey
for an unreleased segwit version is handled successfully.
* Added a test that verifies that
if node has op_shutdown_anysegwit disabled,
a scriptpubkey with an unreleased segwit version on shutdown
throws an error.
* Added peer InitFeatures to handle_shutdown
* Check if shutdown script is valid when given upfront.
* Added a test to verify that an invalid test results in error.
* Added a test to check that if a segwit script with version 0 is provided,
the updated anysegwit check detects it and returns unsupported.
* An empty script is only allowed when sent as upfront shutdown script,
so make sure that check is only done for accept/open_channel situations.
* Instead of reimplementing a variant of is_witness_script,
just call it and verify that the witness version is not 0.
Matt Corallo [Tue, 16 Feb 2021 21:30:08 +0000 (16:30 -0500)]
Rename ChannelKeys -> Sign and generic it consistently
The `ChannelKeys` object really isn't about keys at all anymore,
its all about signing. At the same time, we rename the type aliases
used in traits from both `ChanKeySigner` and `Keys` to just
`Signer` (or, in contexts where Channel isnt clear, `ChanSigner`).
This will allow the ChannelManager to signal when it has new
updates to persist, and adds a way for ChannelManager persisters
to be notified when they should re-persist the ChannelManager
to disk/backups.
Feature-gate the wait_timeout function because the core
lightning crate shouldn't depend on wallclock time unless
users opt into it.
Matt Corallo [Fri, 19 Feb 2021 17:51:07 +0000 (12:51 -0500)]
[bindings] Correctly use access string in to-Rust container conv
`from_c_conversion_container_new_var` should use var_access when
it wishes to access the variable being converted, not `var_name`,
but in a few cases it did not. Note that this has no impact on the
generated bindings as of this commit.
Matt Corallo [Fri, 19 Feb 2021 18:08:54 +0000 (13:08 -0500)]
Switch from slice to slice-of-refs for spend_spendable_outputs
Sadly, there's just not really a practical way to map a slice of
objects in our current bindings infrastructure - either we take
ownership of the underlying objects and move them into a Vec, or we
need to leave the original objects in place and have a list of
pointers to the Rust objects. Thus, the only practical mapping is
to create a slice of references using the pointers we have.
Matt Corallo [Thu, 11 Feb 2021 16:47:51 +0000 (11:47 -0500)]
[bindings] Handle generic-ized impl blocks by concretizing them
This handles, for example, the `impl<X: Y> for Features<X>` blocks
which are generic across a number of different contexts. We do so
by walking the set of structs which alias Features and then walking
their generic arguments to check that they meet the bounds
specified in the impl block. For each alias which does, we create
a dummy, explicit, `impl XFeatures` block with the same content as
the original and recurse.
Matt Corallo [Thu, 11 Feb 2021 16:39:21 +0000 (11:39 -0500)]
[bindings] Resolve type aliases mapped as opaque types
We already map type aliases which alias private types as opaque,
but we don't resolve them like we would any other opaque type,
preventing conversion printing or type use.
Matt Corallo [Thu, 11 Feb 2021 15:23:41 +0000 (10:23 -0500)]
Drop a useless import and use `Self` in return values in Features
`Result` is in the standard prelude, so no need to ever use it.
Sadly, returning a Features<T> in the `impl Futures {}` block
will confuse our new alias-impl-printing logic, as we end up
running through the normal impl-block-printing logic as if we had
an explicit `impl ConcreteFeatures` block.