-
Notifications
You must be signed in to change notification settings - Fork 24
smite-ir: add RecvShutdown operation #163
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,7 +11,7 @@ use smite::bolt::{ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| AcceptChannel, AnnouncementSignatures, ChannelAnnouncement, ChannelId, ChannelReady, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ChannelReadyTlvs, ChannelUpdate, Features, FromMessage, FundingCreated, FundingSigned, Message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MessageType, NodeAnnouncement, OpenChannel, OpenChannelTlvs, Pong, ShortChannelId, Shutdown, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TemporaryChannelId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TemporaryChannelId, is_standard_shutdown_script, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| use smite::channel_tx::{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ChannelConfig, ChannelPartyConfig, ChannelState, FundingTransaction, HolderIdentity, Side, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -484,14 +484,14 @@ impl<C: Connection, B: BitcoinRpc, R: TargetRpc> Executor<C, B, R> { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operation::SendShutdown => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let sd = build_shutdown(&variables, &instr.inputs); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let encoded = Message::Shutdown(sd).encode(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let encoded = Message::Shutdown(sd.clone()).encode(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log::debug!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "[{:?}] SendShutdown: {} bytes", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start.elapsed(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoded.len() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.conn.send_message(&encoded)?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(Variable::SentShutdown) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(Variable::SentShutdown(sd)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operation::RecvAcceptChannel => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -538,6 +538,40 @@ impl<C: Connection, B: BitcoinRpc, R: TargetRpc> Executor<C, B, R> { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operation::RecvShutdown => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let Variable::SentShutdown(sent) = consume_affine( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &mut variables, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| instr.inputs[0], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| instr.operation.input_types()[0], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| unreachable!("consume_affine checked the variable type"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: we only expect `shutdown` when all HTLCs are resolved, else this is a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // no-op. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let reply = if is_shutdown_expected(&self.channel_states, sent.channel_id) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log::debug!("[{:?}] RecvShutdown: waiting", start.elapsed()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let reply = recv_shutdown_reply( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &mut self.conn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &sent, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| &self.context.negotiated_features, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log::debug!("[{:?}] RecvShutdown: received", start.elapsed()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reply | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match reply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(sd) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.channel_states | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get_mut(&sent.channel_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("is_shutdown_expected guarantees a tracked channel") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .counterparty_shutdown_received = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Some(Variable::Bytes(sd.scriptpubkey)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| None => Some(Variable::Bytes(Vec::new())), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+551
to
+572
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this code is over-complicated. If
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operation::MineBlocks(v) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Clear the private mempool and mine the requested blocks, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // adding those transactions to the first block. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -681,8 +715,12 @@ define_resolver!( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Consumes an affine variable, leaving its slot void so it cannot be used | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// again. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn consume_affine(variables: &mut [Option<Variable>], index: usize, expected: VariableType) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// again, and returns it. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn consume_affine( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variables: &mut [Option<Variable>], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| index: usize, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expected: VariableType, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Variable { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expected.is_affine(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "consume_affine called with non-affine type {expected:?}; voiding the slot would break later reads" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -691,7 +729,9 @@ fn consume_affine(variables: &mut [Option<Variable>], index: usize, expected: Va | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if actual != expected { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type_mismatch(index, expected, actual); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variables[index] = None; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| variables[index] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .take() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .expect("resolve checked the slot is not void") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // -- Operation handlers -- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1247,6 +1287,60 @@ fn is_channel_ready_expected( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Returns `true` if the target still owes us a `shutdown` response on the given channel. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn is_shutdown_expected( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| channel_states: &HashMap<ChannelId, ChannelState>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| channel_id: ChannelId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> bool { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: we don't know for sure if the target will reply because if a target didn't reply with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // `channel_ready` yet, it MAY reply with `shutdown` (but doesn't have to) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1295
to
+1296
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we also check for this case? We could just check whether the PCP exists in the channel state. We would avoid some 1s timeouts on targets that don't reply, but lose some edge case coverage on targets that do reply. WDYT? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: once the target has replied, a duplicate `shutdown` from it goes unread here | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| channel_states | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get(&channel_id) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .is_some_and(|state| !state.counterparty_shutdown_received) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Receives the target's reply to our `shutdown`, or `None` if it sent a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `warning` for our channel instead, which BOLT 2 allows when our | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// `scriptpubkey` is non-standard. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// # Errors | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Returns [`ExecuteError::UnexpectedMessage`] if the received message is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// neither a `shutdown` nor such a `warning`, or is a `shutdown` for another | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// channel. That may answer a `shutdown` we sent there earlier, which we can't | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// check against the `shutdown` we sent on this channel. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fn recv_shutdown_reply( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn: &mut impl Connection, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sent: &Shutdown, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| negotiated_features: &Features, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> Result<Option<Shutdown>, ExecuteError> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let may_warn = !is_standard_shutdown_script(&sent.scriptpubkey, negotiated_features); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| match recv_non_ping(conn, RECV_IDLE_TIMEOUT)? { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Message::Shutdown(sd) if sd.channel_id == sent.channel_id => Ok(Some(sd)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Message::Shutdown(sd) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log::debug!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "received shutdown on {} while waiting on {}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sd.channel_id, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sent.channel_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1322
to
+1326
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it makes sense to flag this as an error -- we can handle any |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Err(ExecuteError::UnexpectedMessage { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expected: MessageType::SHUTDOWN, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| got: MessageType::SHUTDOWN, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Message::Warning(w) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if may_warn && (w.channel_id == sent.channel_id || w.channel_id == ChannelId::ALL) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(None) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1332
to
+1336
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it makes sense to handle this warning. It looks like every impl except LDK will disconnect us after sending We could just stop execution like we usually do on warnings. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| other => Err(ExecuteError::UnexpectedMessage { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expected: MessageType::SHUTDOWN, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| got: other.msg_type(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// Records a sent `open_channel`, keyed by `temporary_channel_id`, so the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// funding flow can build commitments from the values actually put on the wire. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the first affine variable to contain actual data, and I don't think we really need to do this.
We could make
RecvShutdownlikeRecvChannelReadyand record our shutdown script in the channel state when we sendshutdown. Then no matter whichshutdownwe get a response for, we can look it's channel up in the channel state to get our script.