Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Channel Monitor without broadcasting transactions #3396

Closed

Conversation

yellowred
Copy link
Contributor

@yellowred yellowred commented Nov 5, 2024

Allowing Channel Monitor to be updated without executing any commands outside ChannelMonitor. This allows reading Channel Monitor in MonitorUpdatingPersister without using broadcaster and fee estimator and broadcast claims when the node is ready for it.
For example, in a multi tenant environment, a server could load channels data in one place, initialize auxiliary services and perform node configuration, then send the result to another process, that would start a node with all required background processes and one of these processes would broadcast the transactions.

  • Is it safe to loose returned transactions?

Allowing Channel Monitor to be updated without executing any commands outside
ChannelMonitor. This allows reading Channel Monitor in MonitorUpdatingPersister
without using broadcaster and fee estimator and broadcast claims when the node
is ready for it.
@yellowred yellowred force-pushed the oleg_cmo_update_no_broadcast branch from 4ef16ab to fb6efe4 Compare November 5, 2024 05:08
@yellowred
Copy link
Contributor Author

@TheBlueMatt Replaced private update_monitor with update_monitor_opt_broadcast. Appreciate if you could take a look to confirm if it goes in the right direction. Specifically If it is ok to make broadcaster optional in private functions so that they may return claims rather than broadcasting them.

@TheBlueMatt
Copy link
Collaborator

Instead of touching all the code here, wouldn't it be simpler to just build a Broadcaster that stores the packages and use that as the Broadcaster passed to the inner methods?

&self,
updates: &ChannelMonitorUpdate,
logger: &L,
) ->Result<(Vec<Result<Vec<PackageTemplate>, ()>>, bool), ()>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sold on returning the packages to broadcast here - if a user is running in a situation where they don't have the ability to register a Broadcaster that can broadcast why can they broadcast a set of transactions we hand to them here? Instead, should we consider storing the packages in the ChannelMonitor to broadcast as soon as we see the node being up (eg a block gets connected)?

@yellowred
Copy link
Contributor Author

Instead of touching all the code here, wouldn't it be simpler to just build a Broadcaster that stores the packages and use that as the Broadcaster passed to the inner methods?

Followed this advice and implemented VecBroadcaster that does not broadcast transactions immediately, but accumulates them first:

/// Transaction broadcaster that does not broadcast transactions, but accumulates
/// them in a Vec instead. This could be used to delay broadcasts until the system
/// is ready.
pub struct VecBroadcaster {
    channel_id: ChannelId,
    transactions: Mutex<Vec<Transaction>>,
}

impl VecBroadcaster {
    /// Create a new broadcaster for a channel
    pub fn new(channel_id: ChannelId) -> Self {
        Self {
            channel_id,
            transactions: Mutex::new(Vec::new()),
        }
    }

    /// Used to actually broadcast stored transactions to the network.
    #[instrument(skip_all, fields(channel = %self.channel_id))]
    pub fn release_transactions(&self, broadcaster: Arc<dyn BroadcasterInterface>) {
        let transactions = self.transactions.lock();
        info!(
            "Releasing transactions for channel_id={}, len={}",
            self.channel_id,
            transactions.len()
        );
        broadcaster.broadcast_transactions(&transactions.iter().collect::<Vec<&Transaction>>())
    }
}

impl BroadcasterInterface for VecBroadcaster {
    fn broadcast_transactions(&self, txs: &[&Transaction]) {
        let mut tx_storage = self.transactions.lock();
        for tx in txs {
            tx_storage.push((*tx).to_owned())
        }
    }
}

Will close this PR.

@yellowred yellowred closed this Nov 12, 2024
@yellowred yellowred deleted the oleg_cmo_update_no_broadcast branch November 12, 2024 20:46
@TheBlueMatt
Copy link
Collaborator

We could still take that upstream as a part of ChannelMonitor, though indeed its not all that hard to build outside of LDK.

@yellowred yellowred restored the oleg_cmo_update_no_broadcast branch November 27, 2024 00:23
@yellowred
Copy link
Contributor Author

@TheBlueMatt Hey, yeah, that would be useful to have. I drafted another PR with CMon that stores claims in inner and then releases them on block_connected #3428

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants