diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 3107139d2..dcfb42fdd 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -13,6 +13,7 @@ jobs: - open-use-close-a-channel - udt - xudt + - reestablish release: - "0.116.1" name: e2e test for ${{ matrix.workflow }} diff --git a/docs/specs/cross-chain-htlc.md b/docs/specs/cross-chain-htlc.md new file mode 100644 index 000000000..0b62b15ae --- /dev/null +++ b/docs/specs/cross-chain-htlc.md @@ -0,0 +1,80 @@ +# Payment Channel Cross-Chain Protocol with HTLC + +## Synopsis + +In the rapidly evolving world of blockchain technology, interoperability between different networks is becoming increasingly crucial. One of the most promising solutions to this challenge is the use of payment channel cross-chain protocols based on Hash Time-Locked Contracts (HTLCs). This post will delve into how HTLCs can be used to ensure atomic payments across different blockchain networks using the same preimage. + +## What is HTLC? + +Hash Time-Locked Contracts (HTLCs) are a type of smart contract used to facilitate conditional payments. They are designed to ensure that a transaction is either completed within a specified timeframe or canceled. The key components of an HTLC are: + +1. **Hashlock**: A cryptographic hash of a secret (preimage) that must be revealed to complete the transaction. +2. **Timelock**: A time constraint that ensures the transaction is either completed within a certain period or reverted. + +## Cross-Chain Payments with HTLC + +Cross-chain payments involve transferring value across different blockchain networks, which can be difficult due to the absence of direct interoperability. To address this challenge, Hashed Time Lock Contracts (HTLCs) offer a solution by facilitating atomic swaps. These swaps guarantee that transactions are either executed in full or not at all, eliminating the possibility of partial transfers. + +To ensure stability in cross-chain payments, the assets utilized in different blockchain networks must maintain a fixed swap ratio. For instance, the Bitcoin payment channel exclusively supports BTC. Meanwhile, CKB can incorporate a wrapped BTC token via the UDT channel, establishing a consistent 1:1 ratio with Bitcoin. + +Another requirement is that the two networks must use the same hash algorithm for HTLCs. + +## Specification + +The protocol has three actors: + +- Alice in the Blockchain A who wants to send funds to Bob. +- Bob in the Blockchain B who wants to receive funds from Alice. +- Ingrid is the cross-chain hub service provider who runs the payment channel nodes for both Blockchain A and Blockchain B. + +To understand how HTLCs can be used for cross-chain payments, let's break down the process: + +1. **Negotiating**: + - Bob wants to receive $N_b$ amount of asset $T_b$ in the Blockchain B. + - Alice negotiates with Ingrid that if Alice pays $N_a$ amount of asset $T_b$ in the Blockchain A to Ingrid, Ingrid will send $N_b$ amount of asset $T_b$ to Bob in the Blockchain B. + +2. **Offering HTLCs**: + - Alice offers an HTLC with $N_a$ amount of $T_a$ on Blockchain A to Ingrid, locking her funds with a hashlock and a timelock. The hashlock is derived from a secret preimage $S$ that only Bob knows. + - Ingrid, upon receiving the hashlock from Alice, creates a corresponding HTLC on Blockchain B with $N_b$ amount of $T_b$, locking his funds with the same hashlock and a timelock. + +3. **Revealing the Preimage**: + - To claim the funds on Blockchain B, Bob must reveal the preimage to Ingrid. + - Once Ingrid has the preimage, he can use it to unlock the funds on Blockchain A. + - Both transactions are completed atomically, meaning either both are completed, or neither is. + +## Example Between Bitcoin and CKB + +### Setup + +- Alice is in the Blockchain CKB and runs a CFN (CKB Fiber Network) node. +- Bob is in the Blockchain Bitcoin and runs any BOLT compatible lightning node. +- Ingrid is the cross-chain hub service provider who runs both a CFN node in CKB and a BOLT lighting node in Bitcoin. +- The asset used in Blockchain Bitcoin ($T_b$) is BTC. +- Ingrid configures a UDT asset $T_a$ in CKB as the wrapped BTC. + +### From CKB to Bitcoin + +- Bob wants to receive $X$ BTC in Bitcoin. +- Alice negotiates the swap with Ingrid that if Alice sends $X+F$ wrapped BTC in CKB to Ingrid, Ingrid with send $X$ BTC in Bitcoin to Bob. Ingrid will keep $F$ BTC as the fee. + +### From Bitcoin to CKB + +- Alice wants to receive $X$ wrapped BTC in CKB. +- Alice negotiates the swap with Ingrid that if Bob sends $X+F$ BTC in Bitcoin to Ingrid, Ingrid with send $X$ wrapped BTC in CKB to Alice. Ingrid will keep $F$ wrapped BTC as the fee. + +## Benefits of Using HTLC for Cross-Chain Payments + +1. **Security**: The use of cryptographic hash functions ensures that the transactions are secure and tamper-proof. +2. **Atomicity**: The all-or-nothing nature of HTLCs ensures that funds are not lost or stuck in limbo. +3. **Interoperability**: HTLCs enable seamless value transfer between different blockchain networks without the need for a trusted third party. +4. **Compatibility**: The HTLC cross-chain protocol can seamlessly integrate with the existing Bitcoin payment channel network without requiring any modifications. + +## Future Works + +While HTLCs have proven to be a valuable tool for enabling secure cross-chain payments, future research is exploring the potential of Point Time-Locked Contracts (PTLCs) as an improvement over the current HTLC design. PTLCs replace the hash function used in HTLCs with a public key cryptography scheme, offering several advantages: + +- Improved privacy: PTLCs hide the payment hash, making it more difficult for observers to link payments across different hops in the network. +- Reduced on-chain footprint: By using adaptor signatures, PTLCs can reduce the amount of data that needs to be stored on-chain, leading to lower transaction fees and improved scalability. +- Enhanced security: PTLCs are less vulnerable to certain types of attacks, such as the wormhole attack, which can be used to steal funds in HTLC-based payment channels. + +Migrating from HTLCs to PTLCs could potentially unlock new possibilities for cross-chain protocols, enabling more private, efficient, and secure value transfer across different blockchain networks. As the technology matures and wildly adopted in Bitcoin, it is likely that more projects will explore the use of PTLCs to enhance their cross-chain payment capabilities and drive further innovation in the blockchain ecosystem. diff --git a/src/ckb/channel.rs b/src/ckb/channel.rs index 50a8d0764..64b1b52ed 100644 --- a/src/ckb/channel.rs +++ b/src/ckb/channel.rs @@ -46,8 +46,8 @@ use super::{ serde_utils::EntityHex, types::{ AcceptChannel, AddTlc, CFNMessage, ChannelReady, ClosingSigned, CommitmentSigned, Hash256, - LockTime, OpenChannel, Privkey, Pubkey, RemoveTlc, RemoveTlcReason, RevokeAndAck, - TxCollaborationMsg, TxComplete, TxUpdate, + LockTime, OpenChannel, Privkey, Pubkey, ReestablishChannel, RemoveTlc, RemoveTlcReason, + RevokeAndAck, TxCollaborationMsg, TxComplete, TxUpdate, }, NetworkActorCommand, NetworkActorEvent, NetworkActorMessage, }; @@ -289,8 +289,9 @@ impl ChannelActor { )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); - state.state = - ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::empty()); + state.update_state(ChannelState::AwaitingChannelReady( + AwaitingChannelReadyFlags::empty(), + )); return Ok(()); }; @@ -403,8 +404,11 @@ impl ChannelActor { state.maybe_transition_to_shutdown(&self.network)?; Ok(()) } - - _ => { + CFNMessage::ReestablishChannel(reestablish_channel) => { + state.handle_reestablish_channel_message(reestablish_channel, &self.network)?; + Ok(()) + } + CFNMessage::TxAbort(_) | CFNMessage::TxInitRBF(_) | CFNMessage::TxAckRBF(_) => { warn!("Received unsupported message: {:?}", &message); Ok(()) } @@ -485,6 +489,11 @@ impl ChannelActor { version, &tx, &signature ); + debug!( + "Sending next local nonce {:?} (previous nonce {:?})", + state.get_next_local_nonce(), + state.get_local_nonce().borrow() + ); let commitment_signed = CommitmentSigned { channel_id: state.get_id(), partial_signature: signature, @@ -517,10 +526,6 @@ impl ChannelActor { match flags { CommitmentSignedFlags::SigningCommitment(flags) => { let flags = flags | SigningCommitmentFlags::OUR_COMMITMENT_SIGNED_SENT; - // Normally commitment number will be incremented after received a RevokeAndAck message. - // But here channel has not been etablished yet, so we will not receive RevokeAndAck message. - // We increment the commitment number here instead. - state.increment_local_commitment_number(); state.update_state(ChannelState::SigningCommitment(flags)); state.maybe_transition_to_tx_signatures(flags, &self.network)?; } @@ -1090,8 +1095,9 @@ where // TODO: note that we can't actually guarantee that this OpenChannel message is sent here. // It is even possible that the peer_id is bogus, and we can't send a message to it. // We need some book-keeping service to remove all the OUR_INIT_SENT channels. - channel.state = - ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT); + channel.update_state(ChannelState::NegotiatingFunding( + NegotiatingFundingFlags::OUR_INIT_SENT, + )); debug!( "Channel to peer {:?} with id {:?} created: {:?}", &self.peer_id, @@ -1123,10 +1129,28 @@ where Ok(channel) } ChannelInitializationParameter::ReestablishChannel(channel_id) => { - let channel = self + let mut channel = self .store .get_channel_actor_state(&channel_id) .expect("channel should exist"); + channel.reestablishing = true; + + let reestablish_channel = ReestablishChannel { + channel_id, + local_commitment_number: channel.get_current_commitment_number(true), + remote_commitment_number: channel.get_current_commitment_number(false), + }; + + let command = CFNMessageWithPeerId { + peer_id: self.peer_id.clone(), + message: CFNMessage::ReestablishChannel(reestablish_channel), + }; + + self.network + .send_message(NetworkActorMessage::new_command( + NetworkActorCommand::SendCFNMessage(command), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); self.network .send_message(NetworkActorMessage::new_event( @@ -1150,8 +1174,22 @@ where ) -> Result<(), ActorProcessingErr> { match message { ChannelActorMessage::PeerMessage(message) => { - if let Err(error) = self.handle_peer_message(state, message) { - error!("Error while processing channel message: {:?}", error); + if state.reestablishing { + match message { + CFNMessage::ReestablishChannel(reestablish_channel) => { + state.handle_reestablish_channel_message( + reestablish_channel, + &self.network, + )?; + } + _ => { + debug!("Ignoring message while reestablishing: {:?}", message); + } + } + } else { + if let Err(error) = self.handle_peer_message(state, message) { + error!("Error while processing channel message: {:?}", error); + } } } ChannelActorMessage::Command(command) => { @@ -1404,6 +1442,11 @@ pub struct ChannelActorState { pub local_shutdown_fee_rate: Option, pub remote_shutdown_fee_rate: Option, pub remote_shutdown_signature: Option, + pub remote_shutdown_fee: Option, + + // A flag to indicate whether the channel is reestablishing, we won't process any messages until the channel is reestablished. + pub reestablishing: bool, + // A redundant field to record the total amount of the channel. // Used only for debugging purposes. #[cfg(debug_assertions)] @@ -1594,10 +1637,10 @@ impl ChannelActorState { second_commitment_point: Pubkey, ) -> Self { let signer = InMemorySigner::generate_from_seed(seed); - let local_pubkeys = signer.to_channel_public_keys(INITIAL_COMMITMENT_NUMBER); + let local_base_pubkeys = signer.get_base_public_keys(); let channel_id = derive_channel_id_from_revocation_keys( - &local_pubkeys.revocation_base_key, + &local_base_pubkeys.revocation_base_key, &remote_pubkeys.revocation_base_key, ); @@ -1621,7 +1664,7 @@ impl ChannelActorState { tlcs: Default::default(), local_shutdown_script: None, local_channel_parameters: ChannelParametersOneParty { - pubkeys: local_pubkeys, + pubkeys: local_base_pubkeys, selected_contest_delay: remote_delay, }, signer, @@ -1640,6 +1683,7 @@ impl ChannelActorState { local_reserved_ckb_amount, remote_reserved_ckb_amount, + reestablishing: false, #[cfg(debug_assertions)] total_amount: local_value + remote_value, } @@ -1656,7 +1700,7 @@ impl ChannelActorState { to_local_delay: LockTime, ) -> Self { let signer = InMemorySigner::generate_from_seed(seed); - let local_pubkeys = signer.to_channel_public_keys(INITIAL_COMMITMENT_NUMBER); + let local_pubkeys = signer.get_base_public_keys(); let temp_channel_id = derive_temp_channel_id_from_revocation_key(&local_pubkeys.revocation_base_key); Self { @@ -1690,6 +1734,7 @@ impl ChannelActorState { local_reserved_ckb_amount, remote_reserved_ckb_amount: 0, + reestablishing: false, #[cfg(debug_assertions)] total_amount: value, } @@ -1742,6 +1787,38 @@ impl ChannelActorState { self.state = new_state; } + // Send RevokeAndAck message to the counterparty, and update the + // channel state accordingly. + fn send_revoke_and_ack_message(&mut self, network: &ActorRef) { + // Now we should revoke previous transation by revealing preimage. + let old_number = self.get_remote_commitment_number(); + let secret = self.signer.get_commitment_secret(old_number); + + self.update_state_on_raa_msg(false); + + let new_number = self.get_remote_commitment_number(); + let point = self.get_local_commitment_point(new_number); + + debug!( + "Revealing revocation preimage #{}: {:?}", + old_number, &secret + ); + debug!("Sending new commitment point #{}: {:?}", new_number, &point); + + network + .send_message(NetworkActorMessage::new_command( + NetworkActorCommand::SendCFNMessage(CFNMessageWithPeerId { + peer_id: self.peer_id.clone(), + message: CFNMessage::RevokeAndAck(RevokeAndAck { + channel_id: self.get_id(), + per_commitment_secret: secret.into(), + next_per_commitment_point: point, + }), + }), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); + } + // After sending or receiving a RevokeAndAck message, all messages before // are considered confirmed by both parties. These messages include // AddTlc and RemoveTlc to operate on TLCs. @@ -1841,8 +1918,13 @@ impl ChannelActorState { self.id } + pub fn get_local_secnonce(&self) -> SecNonce { + self.signer + .derive_musig2_nonce(self.get_local_commitment_number()) + } + pub fn get_local_nonce(&self) -> impl Borrow { - self.get_next_local_secnonce().public_nonce() + self.get_local_secnonce().public_nonce() } pub fn get_next_local_secnonce(&self) -> SecNonce { @@ -1851,9 +1933,7 @@ impl ChannelActorState { } pub fn get_next_local_nonce(&self) -> PubNonce { - self.signer - .derive_musig2_nonce(self.get_next_commitment_number(true)) - .public_nonce() + self.get_next_local_secnonce().public_nonce().clone() } pub fn get_remote_nonce(&self) -> &PubNonce { @@ -1872,11 +1952,29 @@ impl ChannelActorState { self.commitment_numbers.get_remote() } + fn set_remote_commitment_number(&mut self, number: u64) { + debug!( + "Setting remote commitment number from {} to {}", + self.commitment_numbers.remote, number + ); + self.commitment_numbers.remote = number; + } + pub fn increment_local_commitment_number(&mut self) { + debug!( + "Incrementing local commitment number from {} to {}", + self.get_local_commitment_number(), + self.get_local_commitment_number() + 1 + ); self.commitment_numbers.increment_local(); } pub fn increment_remote_commitment_number(&mut self) { + debug!( + "Incrementing remote commitment number from {} to {}", + self.get_remote_commitment_number(), + self.get_remote_commitment_number() + 1 + ); self.commitment_numbers.increment_remote(); } @@ -2147,6 +2245,12 @@ impl ChannelActorState { let local_nonce = local_nonce.borrow(); let remote_nonce = self.get_remote_nonce(); let nonces = self.order_things_for_musig2(local_nonce, remote_nonce); + debug!( + "Got agg nonces {:?} from peer {:?}: {:?}", + AggNonce::sum(nonces), + &self.peer_id, + nonces + ); AggNonce::sum(nonces) } @@ -2452,19 +2556,6 @@ impl ChannelActorState { } } -impl From<&ChannelActorState> for Musig2Context { - fn from(value: &ChannelActorState) -> Self { - Musig2Context { - key_agg_ctx: value.get_musig2_agg_context(), - agg_nonce: value.get_musig2_agg_pubnonce(), - local_seckey: value.signer.funding_key, - local_secnonce: value.get_local_musig2_secnonce(), - remote_pubkey: *value.get_remote_funding_pubkey(), - remote_pubnonce: value.get_remote_nonce().clone(), - } - } -} - impl From<&ChannelActorState> for Musig2SignContext { fn from(value: &ChannelActorState) -> Self { Musig2SignContext { @@ -2869,46 +2960,20 @@ impl ChannelActorState { )) .expect(ASSUME_NETWORK_ACTOR_ALIVE); - debug!("Updating peer next local nonce"); + debug!( + "Updating peer next remote nonce from {:?} to {:?}", + self.get_remote_nonce(), + &commitment_signed.next_local_nonce + ); self.remote_nonce = Some(commitment_signed.next_local_nonce); match flags { CommitmentSignedFlags::SigningCommitment(flags) => { - // Normally commitment number will be incremented after sent a RevokeAndAck message. - // But here channel has not been etablished yet, so we will not send RevokeAndAck message. - // We increment the commitment number here instead. - self.increment_remote_commitment_number(); let flags = flags | SigningCommitmentFlags::THEIR_COMMITMENT_SIGNED_SENT; self.update_state(ChannelState::SigningCommitment(flags)); self.maybe_transition_to_tx_signatures(flags, network)?; } CommitmentSignedFlags::ChannelReady() | CommitmentSignedFlags::PendingShutdown(_) => { - // Now we should revoke previous transation by revealing preimage. - let old_number = self.get_remote_commitment_number(); - let secret = self.signer.get_commitment_secret(old_number); - - self.update_state_on_raa_msg(false); - - let new_number = self.get_remote_commitment_number(); - let point = self.get_local_commitment_point(new_number); - - debug!( - "Revealing revocation preimage #{}: {:?}", - old_number, &secret - ); - debug!("Sending new commitment point #{}: {:?}", new_number, &point); - - network - .send_message(NetworkActorMessage::new_command( - NetworkActorCommand::SendCFNMessage(CFNMessageWithPeerId { - peer_id: self.peer_id.clone(), - message: CFNMessage::RevokeAndAck(RevokeAndAck { - channel_id: self.get_id(), - per_commitment_secret: secret.into(), - next_per_commitment_point: point, - }), - }), - )) - .expect(ASSUME_NETWORK_ACTOR_ALIVE); + self.send_revoke_and_ack_message(network); match flags { CommitmentSignedFlags::ChannelReady() => {} CommitmentSignedFlags::PendingShutdown(_) => { @@ -3022,6 +3087,8 @@ impl ChannelActorState { pub fn on_channel_ready(&mut self, network: &ActorRef) { self.update_state(ChannelState::ChannelReady()); + self.increment_local_commitment_number(); + self.increment_remote_commitment_number(); network .send_message(NetworkActorMessage::new_event( NetworkActorEvent::ChannelReady(self.get_id(), self.peer_id.clone()), @@ -3068,6 +3135,123 @@ impl ChannelActorState { Ok(()) } + fn handle_reestablish_channel_message( + &mut self, + reestablish_channel: ReestablishChannel, + network: &ActorRef, + ) -> ProcessingChannelResult { + debug!( + "Handling reestablish channel message: {:?}, our commitment_numbers {:?}", + reestablish_channel, self.commitment_numbers, + ); + self.reestablishing = false; + match self.state { + ChannelState::NegotiatingFunding(_flags) => { + // TODO: in current implementation, we don't store the channel when we are in NegotiatingFunding state. + // This is an unreachable state for reestablish channel message. we may need to handle this case in the future. + } + ChannelState::ChannelReady() => { + let expected_local_commitment_number = self.get_local_commitment_number(); + let acutal_local_commitment_number = reestablish_channel.remote_commitment_number; + if acutal_local_commitment_number == expected_local_commitment_number { + // resend AddTlc, RemoveTlc and CommitmentSigned messages if needed + let mut need_resend_commitment_signed = false; + for info in self.tlcs.values() { + if info.is_offered() { + if info.created_at.get_local() >= acutal_local_commitment_number + && info.creation_confirmed_at.is_none() + { + // resend AddTlc message + network + .send_message(NetworkActorMessage::new_command( + NetworkActorCommand::SendCFNMessage(CFNMessageWithPeerId { + peer_id: self.peer_id.clone(), + message: CFNMessage::AddTlc(AddTlc { + channel_id: self.get_id(), + tlc_id: info.tlc.get_id(), + amount: info.tlc.amount, + payment_hash: info.tlc.payment_hash, + expiry: info.tlc.lock_time, + }), + }), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); + + need_resend_commitment_signed = true; + } + } else { + if let Some((commitment_number, remove_reason)) = info.removed_at { + if commitment_number.get_local() >= acutal_local_commitment_number { + // resend RemoveTlc message + network + .send_message(NetworkActorMessage::new_command( + NetworkActorCommand::SendCFNMessage( + CFNMessageWithPeerId { + peer_id: self.peer_id.clone(), + message: CFNMessage::RemoveTlc(RemoveTlc { + channel_id: self.get_id(), + tlc_id: info.tlc.get_id(), + reason: remove_reason, + }), + }, + ), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); + + need_resend_commitment_signed = true; + } + } + } + } + if need_resend_commitment_signed { + debug!("Resend CommitmentSigned message"); + network + .send_message(NetworkActorMessage::new_command( + NetworkActorCommand::ControlCfnChannel(ChannelCommandWithId { + channel_id: self.get_id(), + command: ChannelCommand::CommitmentSigned(), + }), + )) + .expect(ASSUME_NETWORK_ACTOR_ALIVE); + } + } else if acutal_local_commitment_number == expected_local_commitment_number + 1 { + // wait for remote to resend the RevokeAndAck message, do nothing here + } else { + // unreachable state, just log an error for potential bugs + error!( + "Reestablish channel message with invalid local commitment number: expected {}, actual {}", + expected_local_commitment_number, acutal_local_commitment_number + ); + } + + let expected_remote_commitment_number = self.get_remote_commitment_number(); + let acutal_remote_commitment_number = reestablish_channel.local_commitment_number; + if expected_remote_commitment_number == acutal_remote_commitment_number { + // synced with remote, do nothing + } else if expected_remote_commitment_number == acutal_remote_commitment_number + 1 { + // Resetting our remote commitment number to the actual remote commitment number + // and resend the RevokeAndAck message. + self.set_remote_commitment_number(acutal_remote_commitment_number); + self.send_revoke_and_ack_message(network); + } else { + // unreachable state, just log an error for potential bugs + error!( + "Reestablish channel message with invalid remote commitment number: expected {}, actual {}", + expected_remote_commitment_number, acutal_remote_commitment_number + ); + } + } + _ => { + // TODO: @quake we need to handle other states. + warn!( + "Unhandled reestablish channel message in state {:?}", + &self.state + ); + } + } + Ok(()) + } + pub fn is_tx_final(&self, tx: &Transaction) -> Result { // TODO: check if the tx is valid let tx = tx.clone().into_view(); @@ -3499,7 +3683,12 @@ impl ChannelActorState { self.get_remote_channel_parameters().revocation_base_key(), ) }; - debug!("Got base witness parameters: delayed time: {:?}, delayed_payment_key: {:?}, revocation_key: {:?}", delay, delayed_payment_base_key, revocation_base_key); + debug!( + "Got base witness parameters: delayed_time: {:?}, delayed_payment_key: {:?}, delayed_commitment_point {:?}, revocation_key: {:?}, revocation_commitment point: {:?}", + delay, delayed_payment_base_key, + delayed_payment_commitment_point, + revocation_base_key, revocation_commitment_point + ); ( delay, derive_delayed_payment_pubkey( @@ -3510,6 +3699,11 @@ impl ChannelActorState { ) }; + debug!( + "Parameters for witnesses: epoch {:?}, payment key: {:?}, revocation key: {:?}", + delayed_epoch, delayed_payment_key, revocation_key + ); + // for xudt compatibility issue, // refer to: https://github.com/nervosnetwork/cfn-scripts/pull/5 let empty_witness_args: [u8; 16] = [16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0]; @@ -3788,42 +3982,6 @@ pub fn create_witness_for_funding_cell( .expect("Witness length should be correct") } -pub struct Musig2Context { - pub key_agg_ctx: KeyAggContext, - pub agg_nonce: AggNonce, - pub local_seckey: Privkey, - pub local_secnonce: SecNonce, - pub remote_pubkey: Pubkey, - pub remote_pubnonce: PubNonce, -} - -impl Musig2Context { - pub fn split(self) -> (Musig2SignContext, Musig2VerifyContext) { - let Musig2Context { - key_agg_ctx, - agg_nonce, - local_seckey, - local_secnonce, - remote_pubkey, - remote_pubnonce, - } = self; - ( - Musig2SignContext { - key_agg_ctx: key_agg_ctx.clone(), - agg_nonce: agg_nonce.clone(), - seckey: local_seckey, - secnonce: local_secnonce, - }, - Musig2VerifyContext { - key_agg_ctx, - agg_nonce, - pubkey: remote_pubkey, - pubnonce: remote_pubnonce, - }, - ) - } -} - pub struct Musig2VerifyContext { pub key_agg_ctx: KeyAggContext, pub agg_nonce: AggNonce, @@ -3844,14 +4002,23 @@ impl From for Musig2VerifyContext { impl Musig2VerifyContext { pub fn verify(&self, signature: PartialSignature, message: &[u8]) -> ProcessingChannelResult { - Ok(verify_partial( + let result = verify_partial( &self.key_agg_ctx, signature, &self.agg_nonce, self.pubkey, &self.pubnonce, message, - )?) + ); + debug!( + "Verifying partial signature {:?} with message {:?}, nonce {:?}, agg nonce {:?}, result {:?}", + &signature, + hex::encode(message), + &self.pubnonce, + &self.agg_nonce, + result + ); + Ok(result?) } } @@ -3865,7 +4032,13 @@ pub struct Musig2SignContext { impl Musig2SignContext { pub fn sign(self, message: &[u8]) -> Result { - debug!("Musig2 signing partial message {:?}", hex::encode(&message)); + debug!( + "Musig2 signing partial message {:?} with nonce {:?} (public nonce: {:?}), agg nonce {:?}", + hex::encode(&message), + self.secnonce, + self.secnonce.public_nonce(), + &self.agg_nonce + ); Ok(sign_partial( &self.key_agg_ctx, self.seckey, @@ -4017,6 +4190,13 @@ impl TLC { fn get_hash(&self) -> ShortHash { self.payment_hash.as_ref()[..20].try_into().unwrap() } + + fn get_id(&self) -> u64 { + match self.id { + TLCId::Offered(id) => id, + TLCId::Received(id) => id, + } + } } /// A tlc output in a commitment transaction, including both the tlc output @@ -4068,10 +4248,36 @@ impl DetailedTLCInfo { } } -pub fn derive_private_key(secret: &Privkey, _per_commitment_point: &Pubkey) -> Privkey { - // TODO: Currently we only copy the input secret. We need to actually derive new private keys - // from the per_commitment_point. - *secret +pub fn get_tweak_by_commitment_point(commitment_point: &Pubkey) -> [u8; 32] { + let mut hasher = new_blake2b(); + hasher.update(&commitment_point.serialize()); + let mut result = [0u8; 32]; + hasher.finalize(&mut result); + result +} + +fn derive_private_key(secret: &Privkey, commitment_point: &Pubkey) -> Privkey { + secret.tweak(get_tweak_by_commitment_point(commitment_point)) +} + +fn derive_public_key(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey { + base_key.tweak(get_tweak_by_commitment_point(commitment_point)) +} + +pub fn derive_revocation_pubkey(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey { + derive_public_key(base_key, commitment_point) +} + +pub fn derive_payment_pubkey(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey { + derive_public_key(base_key, commitment_point) +} + +pub fn derive_delayed_payment_pubkey(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey { + derive_public_key(base_key, commitment_point) +} + +pub fn derive_tlc_pubkey(base_key: &Pubkey, commitment_point: &Pubkey) -> Pubkey { + derive_public_key(base_key, commitment_point) } /// A simple implementation of [`WriteableEcdsaChannelSigner`] that just keeps the private keys in memory. @@ -4093,27 +4299,11 @@ pub struct InMemorySigner { pub tlc_base_key: Privkey, /// SecNonce used to generate valid signature in musig. // TODO: use rust's ownership to make sure musig_nonce is used once. - pub musig2_base_nonce: SecNonce, + pub musig2_base_nonce: Privkey, /// Seed to derive above keys (per commitment). pub commitment_seed: [u8; 32], } -pub fn derive_revocation_pubkey(base_key: &Pubkey, _commitment_point: &Pubkey) -> Pubkey { - *base_key -} - -pub fn derive_payment_pubkey(base_key: &Pubkey, _commitment_point: &Pubkey) -> Pubkey { - *base_key -} - -pub fn derive_delayed_payment_pubkey(base_key: &Pubkey, _commitment_point: &Pubkey) -> Pubkey { - *base_key -} - -pub fn derive_tlc_pubkey(base_key: &Pubkey, _commitment_point: &Pubkey) -> Pubkey { - *base_key -} - impl InMemorySigner { pub fn generate_from_seed(params: &[u8]) -> Self { let seed = ckb_hash::blake2b_256(params); @@ -4138,8 +4328,7 @@ impl InMemorySigner { let delayed_payment_base_key = key_derive(payment_key.as_ref(), b"delayed payment base key"); let tlc_base_key = key_derive(delayed_payment_base_key.as_ref(), b"HTLC base key"); - let misig_nonce = key_derive(tlc_base_key.as_ref(), b"musig nocne"); - let musig_nonce = SecNonce::build(misig_nonce.as_ref()).build(); + let musig2_base_nonce = key_derive(tlc_base_key.as_ref(), b"musig nocne"); Self { funding_key, @@ -4147,18 +4336,18 @@ impl InMemorySigner { payment_key, delayed_payment_base_key, tlc_base_key, - musig2_base_nonce: musig_nonce, + musig2_base_nonce, commitment_seed, } } - fn to_channel_public_keys(&self, commitment_number: u64) -> ChannelBasePublicKeys { + fn get_base_public_keys(&self) -> ChannelBasePublicKeys { ChannelBasePublicKeys { funding_pubkey: self.funding_key.pubkey(), - revocation_base_key: self.derive_revocation_key(commitment_number).pubkey(), - payment_base_key: self.derive_payment_key(commitment_number).pubkey(), - delayed_payment_base_key: self.derive_delayed_payment_key(commitment_number).pubkey(), - tlc_base_key: self.derive_tlc_key(commitment_number).pubkey(), + revocation_base_key: self.revocation_base_key.pubkey(), + payment_base_key: self.payment_key.pubkey(), + delayed_payment_base_key: self.delayed_payment_base_key.pubkey(), + tlc_base_key: self.tlc_base_key.pubkey(), } } @@ -4196,18 +4385,20 @@ impl InMemorySigner { derive_private_key(&self.tlc_base_key, &per_commitment_point) } - pub fn derive_musig2_nonce(&self, _new_commitment_number: u64) -> SecNonce { - // TODO: generate new musig nonce here - self.musig2_base_nonce.clone() + // TODO: Verify that this is a secure way to derive the nonce. + pub fn derive_musig2_nonce(&self, commitment_number: u64) -> SecNonce { + let commitment_point = self.get_commitment_point(commitment_number); + let seckey = derive_private_key(&self.musig2_base_nonce, &commitment_point); + debug!( + "Deriving Musig2 nonce: commitment number: {}, commitment point: {:?}", + commitment_number, commitment_point + ); + SecNonce::build(seckey.as_ref()).build() } } #[cfg(test)] mod tests { - - use ckb_jsonrpc_types::Status; - use ractor::call; - use crate::{ ckb::{ network::{AcceptChannelCommand, OpenChannelCommand}, @@ -4217,6 +4408,9 @@ mod tests { NetworkServiceEvent, }; + use ckb_jsonrpc_types::Status; + use ractor::call; + use super::{super::types::Privkey, derive_private_key, derive_tlc_pubkey, InMemorySigner}; #[test] diff --git a/src/ckb/gen/cfn.rs b/src/ckb/gen/cfn.rs index 6867f8978..1579b5e5c 100644 --- a/src/ckb/gen/cfn.rs +++ b/src/ckb/gen/cfn.rs @@ -2914,283 +2914,6 @@ impl<'a> From<&'a PubkeyReader<'a>> for &'a [u8; 33usize] { } } #[derive(Clone)] -pub struct SignatureVec(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for SignatureVec { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for SignatureVec { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for SignatureVec { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} [", Self::NAME)?; - for i in 0..self.len() { - if i == 0 { - write!(f, "{}", self.get_unchecked(i))?; - } else { - write!(f, ", {}", self.get_unchecked(i))?; - } - } - write!(f, "]") - } -} -impl ::core::default::Default for SignatureVec { - fn default() -> Self { - let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); - SignatureVec::new_unchecked(v) - } -} -impl SignatureVec { - const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; - pub const ITEM_SIZE: usize = 64; - pub fn total_size(&self) -> usize { - molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() - } - pub fn item_count(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn len(&self) -> usize { - self.item_count() - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn get(&self, idx: usize) -> Option { - if idx >= self.len() { - None - } else { - Some(self.get_unchecked(idx)) - } - } - pub fn get_unchecked(&self, idx: usize) -> Signature { - let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; - let end = start + Self::ITEM_SIZE; - Signature::new_unchecked(self.0.slice(start..end)) - } - pub fn as_reader<'r>(&'r self) -> SignatureVecReader<'r> { - SignatureVecReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for SignatureVec { - type Builder = SignatureVecBuilder; - const NAME: &'static str = "SignatureVec"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - SignatureVec(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - SignatureVecReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - SignatureVecReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder().extend(self.into_iter()) - } -} -#[derive(Clone, Copy)] -pub struct SignatureVecReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for SignatureVecReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for SignatureVecReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for SignatureVecReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} [", Self::NAME)?; - for i in 0..self.len() { - if i == 0 { - write!(f, "{}", self.get_unchecked(i))?; - } else { - write!(f, ", {}", self.get_unchecked(i))?; - } - } - write!(f, "]") - } -} -impl<'r> SignatureVecReader<'r> { - pub const ITEM_SIZE: usize = 64; - pub fn total_size(&self) -> usize { - molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() - } - pub fn item_count(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn len(&self) -> usize { - self.item_count() - } - pub fn is_empty(&self) -> bool { - self.len() == 0 - } - pub fn get(&self, idx: usize) -> Option> { - if idx >= self.len() { - None - } else { - Some(self.get_unchecked(idx)) - } - } - pub fn get_unchecked(&self, idx: usize) -> SignatureReader<'r> { - let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; - let end = start + Self::ITEM_SIZE; - SignatureReader::new_unchecked(&self.as_slice()[start..end]) - } -} -impl<'r> molecule::prelude::Reader<'r> for SignatureVecReader<'r> { - type Entity = SignatureVec; - const NAME: &'static str = "SignatureVecReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - SignatureVecReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let item_count = molecule::unpack_number(slice) as usize; - if item_count == 0 { - if slice_len != molecule::NUMBER_SIZE { - return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); - } - return Ok(()); - } - let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - Ok(()) - } -} -#[derive(Clone, Debug, Default)] -pub struct SignatureVecBuilder(pub(crate) Vec); -impl SignatureVecBuilder { - pub const ITEM_SIZE: usize = 64; - pub fn set(mut self, v: Vec) -> Self { - self.0 = v; - self - } - pub fn push(mut self, v: Signature) -> Self { - self.0.push(v); - self - } - pub fn extend>(mut self, iter: T) -> Self { - for elem in iter { - self.0.push(elem); - } - self - } - pub fn replace(&mut self, index: usize, v: Signature) -> Option { - self.0 - .get_mut(index) - .map(|item| ::core::mem::replace(item, v)) - } -} -impl molecule::prelude::Builder for SignatureVecBuilder { - type Entity = SignatureVec; - const NAME: &'static str = "SignatureVecBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() - } - fn write(&self, writer: &mut W) -> molecule::io::Result<()> { - writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; - for inner in &self.0[..] { - writer.write_all(inner.as_slice())?; - } - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - SignatureVec::new_unchecked(inner.into()) - } -} -pub struct SignatureVecIterator(SignatureVec, usize, usize); -impl ::core::iter::Iterator for SignatureVecIterator { - type Item = Signature; - fn next(&mut self) -> Option { - if self.1 >= self.2 { - None - } else { - let ret = self.0.get_unchecked(self.1); - self.1 += 1; - Some(ret) - } - } -} -impl ::core::iter::ExactSizeIterator for SignatureVecIterator { - fn len(&self) -> usize { - self.2 - self.1 - } -} -impl ::core::iter::IntoIterator for SignatureVec { - type Item = Signature; - type IntoIter = SignatureVecIterator; - fn into_iter(self) -> Self::IntoIter { - let len = self.len(); - SignatureVecIterator(self, 0, len) - } -} -impl<'r> SignatureVecReader<'r> { - pub fn iter<'t>(&'t self) -> SignatureVecReaderIterator<'t, 'r> { - SignatureVecReaderIterator(&self, 0, self.len()) - } -} -pub struct SignatureVecReaderIterator<'t, 'r>(&'t SignatureVecReader<'r>, usize, usize); -impl<'t: 'r, 'r> ::core::iter::Iterator for SignatureVecReaderIterator<'t, 'r> { - type Item = SignatureReader<'t>; - fn next(&mut self) -> Option { - if self.1 >= self.2 { - None - } else { - let ret = self.0.get_unchecked(self.1); - self.1 += 1; - Some(ret) - } - } -} -impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for SignatureVecReaderIterator<'t, 'r> { - fn len(&self) -> usize { - self.2 - self.1 - } -} -impl ::core::iter::FromIterator for SignatureVec { - fn from_iter>(iter: T) -> Self { - Self::new_builder().extend(iter).build() - } -} -#[derive(Clone)] pub struct OpenChannel(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for OpenChannel { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { @@ -7637,8 +7360,8 @@ impl molecule::prelude::Builder for AddTlcBuilder { } } #[derive(Clone)] -pub struct TlcsSigned(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for TlcsSigned { +pub struct RevokeAndAck(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for RevokeAndAck { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -7647,17 +7370,27 @@ impl ::core::fmt::LowerHex for TlcsSigned { write!(f, "{}", hex_string(self.as_slice())) } } -impl ::core::fmt::Debug for TlcsSigned { +impl ::core::fmt::Debug for RevokeAndAck { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl ::core::fmt::Display for TlcsSigned { +impl ::core::fmt::Display for RevokeAndAck { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "channel_id", self.channel_id())?; - write!(f, ", {}: {}", "signature", self.signature())?; - write!(f, ", {}: {}", "tlc_signatures", self.tlc_signatures())?; + write!( + f, + ", {}: {}", + "per_commitment_secret", + self.per_commitment_secret() + )?; + write!( + f, + ", {}: {}", + "next_per_commitment_point", + self.next_per_commitment_point() + )?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -7665,18 +7398,18 @@ impl ::core::fmt::Display for TlcsSigned { write!(f, " }}") } } -impl ::core::default::Default for TlcsSigned { +impl ::core::default::Default for RevokeAndAck { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); - TlcsSigned::new_unchecked(v) + RevokeAndAck::new_unchecked(v) } } -impl TlcsSigned { - const DEFAULT_VALUE: [u8; 116] = [ - 116, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +impl RevokeAndAck { + const DEFAULT_VALUE: [u8; 113] = [ + 113, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { @@ -7701,31 +7434,31 @@ impl TlcsSigned { let end = molecule::unpack_number(&slice[8..]) as usize; Byte32::new_unchecked(self.0.slice(start..end)) } - pub fn signature(&self) -> Signature { + pub fn per_commitment_secret(&self) -> Byte32 { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - Signature::new_unchecked(self.0.slice(start..end)) + Byte32::new_unchecked(self.0.slice(start..end)) } - pub fn tlc_signatures(&self) -> SignatureVec { + pub fn next_per_commitment_point(&self) -> Pubkey { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; - SignatureVec::new_unchecked(self.0.slice(start..end)) + Pubkey::new_unchecked(self.0.slice(start..end)) } else { - SignatureVec::new_unchecked(self.0.slice(start..)) + Pubkey::new_unchecked(self.0.slice(start..)) } } - pub fn as_reader<'r>(&'r self) -> TlcsSignedReader<'r> { - TlcsSignedReader::new_unchecked(self.as_slice()) + pub fn as_reader<'r>(&'r self) -> RevokeAndAckReader<'r> { + RevokeAndAckReader::new_unchecked(self.as_slice()) } } -impl molecule::prelude::Entity for TlcsSigned { - type Builder = TlcsSignedBuilder; - const NAME: &'static str = "TlcsSigned"; +impl molecule::prelude::Entity for RevokeAndAck { + type Builder = RevokeAndAckBuilder; + const NAME: &'static str = "RevokeAndAck"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - TlcsSigned(data) + RevokeAndAck(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() @@ -7734,10 +7467,10 @@ impl molecule::prelude::Entity for TlcsSigned { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - TlcsSignedReader::from_slice(slice).map(|reader| reader.to_entity()) + RevokeAndAckReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - TlcsSignedReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + RevokeAndAckReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() @@ -7745,13 +7478,13 @@ impl molecule::prelude::Entity for TlcsSigned { fn as_builder(self) -> Self::Builder { Self::new_builder() .channel_id(self.channel_id()) - .signature(self.signature()) - .tlc_signatures(self.tlc_signatures()) + .per_commitment_secret(self.per_commitment_secret()) + .next_per_commitment_point(self.next_per_commitment_point()) } } #[derive(Clone, Copy)] -pub struct TlcsSignedReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for TlcsSignedReader<'r> { +pub struct RevokeAndAckReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for RevokeAndAckReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -7760,17 +7493,27 @@ impl<'r> ::core::fmt::LowerHex for TlcsSignedReader<'r> { write!(f, "{}", hex_string(self.as_slice())) } } -impl<'r> ::core::fmt::Debug for TlcsSignedReader<'r> { +impl<'r> ::core::fmt::Debug for RevokeAndAckReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl<'r> ::core::fmt::Display for TlcsSignedReader<'r> { +impl<'r> ::core::fmt::Display for RevokeAndAckReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "channel_id", self.channel_id())?; - write!(f, ", {}: {}", "signature", self.signature())?; - write!(f, ", {}: {}", "tlc_signatures", self.tlc_signatures())?; + write!( + f, + ", {}: {}", + "per_commitment_secret", + self.per_commitment_secret() + )?; + write!( + f, + ", {}: {}", + "next_per_commitment_point", + self.next_per_commitment_point() + )?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; @@ -7778,7 +7521,7 @@ impl<'r> ::core::fmt::Display for TlcsSignedReader<'r> { write!(f, " }}") } } -impl<'r> TlcsSignedReader<'r> { +impl<'r> RevokeAndAckReader<'r> { pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize @@ -7802,31 +7545,31 @@ impl<'r> TlcsSignedReader<'r> { let end = molecule::unpack_number(&slice[8..]) as usize; Byte32Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn signature(&self) -> SignatureReader<'r> { + pub fn per_commitment_secret(&self) -> Byte32Reader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; - SignatureReader::new_unchecked(&self.as_slice()[start..end]) + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) } - pub fn tlc_signatures(&self) -> SignatureVecReader<'r> { + pub fn next_per_commitment_point(&self) -> PubkeyReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; - SignatureVecReader::new_unchecked(&self.as_slice()[start..end]) + PubkeyReader::new_unchecked(&self.as_slice()[start..end]) } else { - SignatureVecReader::new_unchecked(&self.as_slice()[start..]) + PubkeyReader::new_unchecked(&self.as_slice()[start..]) } } } -impl<'r> molecule::prelude::Reader<'r> for TlcsSignedReader<'r> { - type Entity = TlcsSigned; - const NAME: &'static str = "TlcsSignedReader"; +impl<'r> molecule::prelude::Reader<'r> for RevokeAndAckReader<'r> { + type Entity = RevokeAndAck; + const NAME: &'static str = "RevokeAndAckReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { - TlcsSignedReader(slice) + RevokeAndAckReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 @@ -7866,40 +7609,40 @@ impl<'r> molecule::prelude::Reader<'r> for TlcsSignedReader<'r> { return ve!(Self, OffsetsNotMatch); } Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - SignatureReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - SignatureVecReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Byte32Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + PubkeyReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Ok(()) } } #[derive(Clone, Debug, Default)] -pub struct TlcsSignedBuilder { +pub struct RevokeAndAckBuilder { pub(crate) channel_id: Byte32, - pub(crate) signature: Signature, - pub(crate) tlc_signatures: SignatureVec, + pub(crate) per_commitment_secret: Byte32, + pub(crate) next_per_commitment_point: Pubkey, } -impl TlcsSignedBuilder { +impl RevokeAndAckBuilder { pub const FIELD_COUNT: usize = 3; pub fn channel_id(mut self, v: Byte32) -> Self { self.channel_id = v; self } - pub fn signature(mut self, v: Signature) -> Self { - self.signature = v; + pub fn per_commitment_secret(mut self, v: Byte32) -> Self { + self.per_commitment_secret = v; self } - pub fn tlc_signatures(mut self, v: SignatureVec) -> Self { - self.tlc_signatures = v; + pub fn next_per_commitment_point(mut self, v: Pubkey) -> Self { + self.next_per_commitment_point = v; self } } -impl molecule::prelude::Builder for TlcsSignedBuilder { - type Entity = TlcsSigned; - const NAME: &'static str = "TlcsSignedBuilder"; +impl molecule::prelude::Builder for RevokeAndAckBuilder { + type Entity = RevokeAndAck; + const NAME: &'static str = "RevokeAndAckBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.channel_id.as_slice().len() - + self.signature.as_slice().len() - + self.tlc_signatures.as_slice().len() + + self.per_commitment_secret.as_slice().len() + + self.next_per_commitment_point.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); @@ -7907,28 +7650,28 @@ impl molecule::prelude::Builder for TlcsSignedBuilder { offsets.push(total_size); total_size += self.channel_id.as_slice().len(); offsets.push(total_size); - total_size += self.signature.as_slice().len(); + total_size += self.per_commitment_secret.as_slice().len(); offsets.push(total_size); - total_size += self.tlc_signatures.as_slice().len(); + total_size += self.next_per_commitment_point.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.channel_id.as_slice())?; - writer.write_all(self.signature.as_slice())?; - writer.write_all(self.tlc_signatures.as_slice())?; + writer.write_all(self.per_commitment_secret.as_slice())?; + writer.write_all(self.next_per_commitment_point.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - TlcsSigned::new_unchecked(inner.into()) + RevokeAndAck::new_unchecked(inner.into()) } } #[derive(Clone)] -pub struct RevokeAndAck(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for RevokeAndAck { +pub struct RemoveTlcFulfill(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for RemoveTlcFulfill { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { @@ -7937,325 +7680,15 @@ impl ::core::fmt::LowerHex for RevokeAndAck { write!(f, "{}", hex_string(self.as_slice())) } } -impl ::core::fmt::Debug for RevokeAndAck { +impl ::core::fmt::Debug for RemoveTlcFulfill { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } -impl ::core::fmt::Display for RevokeAndAck { +impl ::core::fmt::Display for RemoveTlcFulfill { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "channel_id", self.channel_id())?; - write!( - f, - ", {}: {}", - "per_commitment_secret", - self.per_commitment_secret() - )?; - write!( - f, - ", {}: {}", - "next_per_commitment_point", - self.next_per_commitment_point() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl ::core::default::Default for RevokeAndAck { - fn default() -> Self { - let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); - RevokeAndAck::new_unchecked(v) - } -} -impl RevokeAndAck { - const DEFAULT_VALUE: [u8; 113] = [ - 113, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]; - pub const FIELD_COUNT: usize = 3; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn channel_id(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn per_commitment_secret(&self) -> Byte32 { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Byte32::new_unchecked(self.0.slice(start..end)) - } - pub fn next_per_commitment_point(&self) -> Pubkey { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[16..]) as usize; - Pubkey::new_unchecked(self.0.slice(start..end)) - } else { - Pubkey::new_unchecked(self.0.slice(start..)) - } - } - pub fn as_reader<'r>(&'r self) -> RevokeAndAckReader<'r> { - RevokeAndAckReader::new_unchecked(self.as_slice()) - } -} -impl molecule::prelude::Entity for RevokeAndAck { - type Builder = RevokeAndAckBuilder; - const NAME: &'static str = "RevokeAndAck"; - fn new_unchecked(data: molecule::bytes::Bytes) -> Self { - RevokeAndAck(data) - } - fn as_bytes(&self) -> molecule::bytes::Bytes { - self.0.clone() - } - fn as_slice(&self) -> &[u8] { - &self.0[..] - } - fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { - RevokeAndAckReader::from_slice(slice).map(|reader| reader.to_entity()) - } - fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { - RevokeAndAckReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) - } - fn new_builder() -> Self::Builder { - ::core::default::Default::default() - } - fn as_builder(self) -> Self::Builder { - Self::new_builder() - .channel_id(self.channel_id()) - .per_commitment_secret(self.per_commitment_secret()) - .next_per_commitment_point(self.next_per_commitment_point()) - } -} -#[derive(Clone, Copy)] -pub struct RevokeAndAckReader<'r>(&'r [u8]); -impl<'r> ::core::fmt::LowerHex for RevokeAndAckReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl<'r> ::core::fmt::Debug for RevokeAndAckReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl<'r> ::core::fmt::Display for RevokeAndAckReader<'r> { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "channel_id", self.channel_id())?; - write!( - f, - ", {}: {}", - "per_commitment_secret", - self.per_commitment_secret() - )?; - write!( - f, - ", {}: {}", - "next_per_commitment_point", - self.next_per_commitment_point() - )?; - let extra_count = self.count_extra_fields(); - if extra_count != 0 { - write!(f, ", .. ({} fields)", extra_count)?; - } - write!(f, " }}") - } -} -impl<'r> RevokeAndAckReader<'r> { - pub const FIELD_COUNT: usize = 3; - pub fn total_size(&self) -> usize { - molecule::unpack_number(self.as_slice()) as usize - } - pub fn field_count(&self) -> usize { - if self.total_size() == molecule::NUMBER_SIZE { - 0 - } else { - (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 - } - } - pub fn count_extra_fields(&self) -> usize { - self.field_count() - Self::FIELD_COUNT - } - pub fn has_extra_fields(&self) -> bool { - Self::FIELD_COUNT != self.field_count() - } - pub fn channel_id(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[4..]) as usize; - let end = molecule::unpack_number(&slice[8..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn per_commitment_secret(&self) -> Byte32Reader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[8..]) as usize; - let end = molecule::unpack_number(&slice[12..]) as usize; - Byte32Reader::new_unchecked(&self.as_slice()[start..end]) - } - pub fn next_per_commitment_point(&self) -> PubkeyReader<'r> { - let slice = self.as_slice(); - let start = molecule::unpack_number(&slice[12..]) as usize; - if self.has_extra_fields() { - let end = molecule::unpack_number(&slice[16..]) as usize; - PubkeyReader::new_unchecked(&self.as_slice()[start..end]) - } else { - PubkeyReader::new_unchecked(&self.as_slice()[start..]) - } - } -} -impl<'r> molecule::prelude::Reader<'r> for RevokeAndAckReader<'r> { - type Entity = RevokeAndAck; - const NAME: &'static str = "RevokeAndAckReader"; - fn to_entity(&self) -> Self::Entity { - Self::Entity::new_unchecked(self.as_slice().to_owned().into()) - } - fn new_unchecked(slice: &'r [u8]) -> Self { - RevokeAndAckReader(slice) - } - fn as_slice(&self) -> &'r [u8] { - self.0 - } - fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { - use molecule::verification_error as ve; - let slice_len = slice.len(); - if slice_len < molecule::NUMBER_SIZE { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); - } - let total_size = molecule::unpack_number(slice) as usize; - if slice_len != total_size { - return ve!(Self, TotalSizeNotMatch, total_size, slice_len); - } - if slice_len < molecule::NUMBER_SIZE * 2 { - return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); - } - let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; - if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { - return ve!(Self, OffsetsNotMatch); - } - if slice_len < offset_first { - return ve!(Self, HeaderIsBroken, offset_first, slice_len); - } - let field_count = offset_first / molecule::NUMBER_SIZE - 1; - if field_count < Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - } else if !compatible && field_count > Self::FIELD_COUNT { - return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); - }; - let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] - .chunks_exact(molecule::NUMBER_SIZE) - .map(|x| molecule::unpack_number(x) as usize) - .collect(); - offsets.push(total_size); - if offsets.windows(2).any(|i| i[0] > i[1]) { - return ve!(Self, OffsetsNotMatch); - } - Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; - Byte32Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; - PubkeyReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; - Ok(()) - } -} -#[derive(Clone, Debug, Default)] -pub struct RevokeAndAckBuilder { - pub(crate) channel_id: Byte32, - pub(crate) per_commitment_secret: Byte32, - pub(crate) next_per_commitment_point: Pubkey, -} -impl RevokeAndAckBuilder { - pub const FIELD_COUNT: usize = 3; - pub fn channel_id(mut self, v: Byte32) -> Self { - self.channel_id = v; - self - } - pub fn per_commitment_secret(mut self, v: Byte32) -> Self { - self.per_commitment_secret = v; - self - } - pub fn next_per_commitment_point(mut self, v: Pubkey) -> Self { - self.next_per_commitment_point = v; - self - } -} -impl molecule::prelude::Builder for RevokeAndAckBuilder { - type Entity = RevokeAndAck; - const NAME: &'static str = "RevokeAndAckBuilder"; - fn expected_length(&self) -> usize { - molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) - + self.channel_id.as_slice().len() - + self.per_commitment_secret.as_slice().len() - + self.next_per_commitment_point.as_slice().len() - } - fn write(&self, writer: &mut W) -> molecule::io::Result<()> { - let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); - let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); - offsets.push(total_size); - total_size += self.channel_id.as_slice().len(); - offsets.push(total_size); - total_size += self.per_commitment_secret.as_slice().len(); - offsets.push(total_size); - total_size += self.next_per_commitment_point.as_slice().len(); - writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; - for offset in offsets.into_iter() { - writer.write_all(&molecule::pack_number(offset as molecule::Number))?; - } - writer.write_all(self.channel_id.as_slice())?; - writer.write_all(self.per_commitment_secret.as_slice())?; - writer.write_all(self.next_per_commitment_point.as_slice())?; - Ok(()) - } - fn build(&self) -> Self::Entity { - let mut inner = Vec::with_capacity(self.expected_length()); - self.write(&mut inner) - .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); - RevokeAndAck::new_unchecked(inner.into()) - } -} -#[derive(Clone)] -pub struct RemoveTlcFulfill(molecule::bytes::Bytes); -impl ::core::fmt::LowerHex for RemoveTlcFulfill { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - use molecule::hex_string; - if f.alternate() { - write!(f, "0x")?; - } - write!(f, "{}", hex_string(self.as_slice())) - } -} -impl ::core::fmt::Debug for RemoveTlcFulfill { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{}({:#x})", Self::NAME, self) - } -} -impl ::core::fmt::Display for RemoveTlcFulfill { - fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "{} {{ ", Self::NAME)?; - write!(f, "{}: {}", "payment_preimage", self.payment_preimage())?; + write!(f, "{}: {}", "payment_preimage", self.payment_preimage())?; write!(f, " }}") } } @@ -9134,6 +8567,315 @@ impl molecule::prelude::Builder for RemoveTlcBuilder { } } #[derive(Clone)] +pub struct ReestablishChannel(molecule::bytes::Bytes); +impl ::core::fmt::LowerHex for ReestablishChannel { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl ::core::fmt::Debug for ReestablishChannel { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl ::core::fmt::Display for ReestablishChannel { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "channel_id", self.channel_id())?; + write!( + f, + ", {}: {}", + "local_commitment_number", + self.local_commitment_number() + )?; + write!( + f, + ", {}: {}", + "remote_commitment_number", + self.remote_commitment_number() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl ::core::default::Default for ReestablishChannel { + fn default() -> Self { + let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); + ReestablishChannel::new_unchecked(v) + } +} +impl ReestablishChannel { + const DEFAULT_VALUE: [u8; 64] = [ + 64, 0, 0, 0, 16, 0, 0, 0, 48, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + ]; + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn channel_id(&self) -> Byte32 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32::new_unchecked(self.0.slice(start..end)) + } + pub fn local_commitment_number(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } + pub fn remote_commitment_number(&self) -> Uint64 { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint64::new_unchecked(self.0.slice(start..end)) + } else { + Uint64::new_unchecked(self.0.slice(start..)) + } + } + pub fn as_reader<'r>(&'r self) -> ReestablishChannelReader<'r> { + ReestablishChannelReader::new_unchecked(self.as_slice()) + } +} +impl molecule::prelude::Entity for ReestablishChannel { + type Builder = ReestablishChannelBuilder; + const NAME: &'static str = "ReestablishChannel"; + fn new_unchecked(data: molecule::bytes::Bytes) -> Self { + ReestablishChannel(data) + } + fn as_bytes(&self) -> molecule::bytes::Bytes { + self.0.clone() + } + fn as_slice(&self) -> &[u8] { + &self.0[..] + } + fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ReestablishChannelReader::from_slice(slice).map(|reader| reader.to_entity()) + } + fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { + ReestablishChannelReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) + } + fn new_builder() -> Self::Builder { + ::core::default::Default::default() + } + fn as_builder(self) -> Self::Builder { + Self::new_builder() + .channel_id(self.channel_id()) + .local_commitment_number(self.local_commitment_number()) + .remote_commitment_number(self.remote_commitment_number()) + } +} +#[derive(Clone, Copy)] +pub struct ReestablishChannelReader<'r>(&'r [u8]); +impl<'r> ::core::fmt::LowerHex for ReestablishChannelReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + use molecule::hex_string; + if f.alternate() { + write!(f, "0x")?; + } + write!(f, "{}", hex_string(self.as_slice())) + } +} +impl<'r> ::core::fmt::Debug for ReestablishChannelReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{}({:#x})", Self::NAME, self) + } +} +impl<'r> ::core::fmt::Display for ReestablishChannelReader<'r> { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "{} {{ ", Self::NAME)?; + write!(f, "{}: {}", "channel_id", self.channel_id())?; + write!( + f, + ", {}: {}", + "local_commitment_number", + self.local_commitment_number() + )?; + write!( + f, + ", {}: {}", + "remote_commitment_number", + self.remote_commitment_number() + )?; + let extra_count = self.count_extra_fields(); + if extra_count != 0 { + write!(f, ", .. ({} fields)", extra_count)?; + } + write!(f, " }}") + } +} +impl<'r> ReestablishChannelReader<'r> { + pub const FIELD_COUNT: usize = 3; + pub fn total_size(&self) -> usize { + molecule::unpack_number(self.as_slice()) as usize + } + pub fn field_count(&self) -> usize { + if self.total_size() == molecule::NUMBER_SIZE { + 0 + } else { + (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 + } + } + pub fn count_extra_fields(&self) -> usize { + self.field_count() - Self::FIELD_COUNT + } + pub fn has_extra_fields(&self) -> bool { + Self::FIELD_COUNT != self.field_count() + } + pub fn channel_id(&self) -> Byte32Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[4..]) as usize; + let end = molecule::unpack_number(&slice[8..]) as usize; + Byte32Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn local_commitment_number(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[8..]) as usize; + let end = molecule::unpack_number(&slice[12..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } + pub fn remote_commitment_number(&self) -> Uint64Reader<'r> { + let slice = self.as_slice(); + let start = molecule::unpack_number(&slice[12..]) as usize; + if self.has_extra_fields() { + let end = molecule::unpack_number(&slice[16..]) as usize; + Uint64Reader::new_unchecked(&self.as_slice()[start..end]) + } else { + Uint64Reader::new_unchecked(&self.as_slice()[start..]) + } + } +} +impl<'r> molecule::prelude::Reader<'r> for ReestablishChannelReader<'r> { + type Entity = ReestablishChannel; + const NAME: &'static str = "ReestablishChannelReader"; + fn to_entity(&self) -> Self::Entity { + Self::Entity::new_unchecked(self.as_slice().to_owned().into()) + } + fn new_unchecked(slice: &'r [u8]) -> Self { + ReestablishChannelReader(slice) + } + fn as_slice(&self) -> &'r [u8] { + self.0 + } + fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { + use molecule::verification_error as ve; + let slice_len = slice.len(); + if slice_len < molecule::NUMBER_SIZE { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); + } + let total_size = molecule::unpack_number(slice) as usize; + if slice_len != total_size { + return ve!(Self, TotalSizeNotMatch, total_size, slice_len); + } + if slice_len < molecule::NUMBER_SIZE * 2 { + return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); + } + let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; + if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { + return ve!(Self, OffsetsNotMatch); + } + if slice_len < offset_first { + return ve!(Self, HeaderIsBroken, offset_first, slice_len); + } + let field_count = offset_first / molecule::NUMBER_SIZE - 1; + if field_count < Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + } else if !compatible && field_count > Self::FIELD_COUNT { + return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); + }; + let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] + .chunks_exact(molecule::NUMBER_SIZE) + .map(|x| molecule::unpack_number(x) as usize) + .collect(); + offsets.push(total_size); + if offsets.windows(2).any(|i| i[0] > i[1]) { + return ve!(Self, OffsetsNotMatch); + } + Byte32Reader::verify(&slice[offsets[0]..offsets[1]], compatible)?; + Uint64Reader::verify(&slice[offsets[1]..offsets[2]], compatible)?; + Uint64Reader::verify(&slice[offsets[2]..offsets[3]], compatible)?; + Ok(()) + } +} +#[derive(Clone, Debug, Default)] +pub struct ReestablishChannelBuilder { + pub(crate) channel_id: Byte32, + pub(crate) local_commitment_number: Uint64, + pub(crate) remote_commitment_number: Uint64, +} +impl ReestablishChannelBuilder { + pub const FIELD_COUNT: usize = 3; + pub fn channel_id(mut self, v: Byte32) -> Self { + self.channel_id = v; + self + } + pub fn local_commitment_number(mut self, v: Uint64) -> Self { + self.local_commitment_number = v; + self + } + pub fn remote_commitment_number(mut self, v: Uint64) -> Self { + self.remote_commitment_number = v; + self + } +} +impl molecule::prelude::Builder for ReestablishChannelBuilder { + type Entity = ReestablishChannel; + const NAME: &'static str = "ReestablishChannelBuilder"; + fn expected_length(&self) -> usize { + molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + + self.channel_id.as_slice().len() + + self.local_commitment_number.as_slice().len() + + self.remote_commitment_number.as_slice().len() + } + fn write(&self, writer: &mut W) -> molecule::io::Result<()> { + let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); + let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); + offsets.push(total_size); + total_size += self.channel_id.as_slice().len(); + offsets.push(total_size); + total_size += self.local_commitment_number.as_slice().len(); + offsets.push(total_size); + total_size += self.remote_commitment_number.as_slice().len(); + writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; + for offset in offsets.into_iter() { + writer.write_all(&molecule::pack_number(offset as molecule::Number))?; + } + writer.write_all(self.channel_id.as_slice())?; + writer.write_all(self.local_commitment_number.as_slice())?; + writer.write_all(self.remote_commitment_number.as_slice())?; + Ok(()) + } + fn build(&self) -> Self::Entity { + let mut inner = Vec::with_capacity(self.expected_length()); + self.write(&mut inner) + .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); + ReestablishChannel::new_unchecked(inner.into()) + } +} +#[derive(Clone)] pub struct CFNMessage(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for CFNMessage { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { @@ -9193,20 +8935,20 @@ impl CFNMessage { match self.item_id() { 0 => OpenChannel::new_unchecked(inner).into(), 1 => AcceptChannel::new_unchecked(inner).into(), - 2 => CommitmentSigned::new_unchecked(inner).into(), - 3 => TxSignatures::new_unchecked(inner).into(), - 4 => ChannelReady::new_unchecked(inner).into(), - 5 => TxUpdate::new_unchecked(inner).into(), - 6 => TxComplete::new_unchecked(inner).into(), - 7 => TxAbort::new_unchecked(inner).into(), - 8 => TxInitRBF::new_unchecked(inner).into(), - 9 => TxAckRBF::new_unchecked(inner).into(), - 10 => Shutdown::new_unchecked(inner).into(), - 11 => ClosingSigned::new_unchecked(inner).into(), - 12 => AddTlc::new_unchecked(inner).into(), - 13 => TlcsSigned::new_unchecked(inner).into(), - 14 => RevokeAndAck::new_unchecked(inner).into(), - 15 => RemoveTlc::new_unchecked(inner).into(), + 2 => TxSignatures::new_unchecked(inner).into(), + 3 => TxUpdate::new_unchecked(inner).into(), + 4 => TxComplete::new_unchecked(inner).into(), + 5 => TxAbort::new_unchecked(inner).into(), + 6 => TxInitRBF::new_unchecked(inner).into(), + 7 => TxAckRBF::new_unchecked(inner).into(), + 8 => CommitmentSigned::new_unchecked(inner).into(), + 9 => ChannelReady::new_unchecked(inner).into(), + 10 => AddTlc::new_unchecked(inner).into(), + 11 => RemoveTlc::new_unchecked(inner).into(), + 12 => RevokeAndAck::new_unchecked(inner).into(), + 13 => Shutdown::new_unchecked(inner).into(), + 14 => ClosingSigned::new_unchecked(inner).into(), + 15 => ReestablishChannel::new_unchecked(inner).into(), _ => panic!("{}: invalid data", Self::NAME), } } @@ -9272,20 +9014,20 @@ impl<'r> CFNMessageReader<'r> { match self.item_id() { 0 => OpenChannelReader::new_unchecked(inner).into(), 1 => AcceptChannelReader::new_unchecked(inner).into(), - 2 => CommitmentSignedReader::new_unchecked(inner).into(), - 3 => TxSignaturesReader::new_unchecked(inner).into(), - 4 => ChannelReadyReader::new_unchecked(inner).into(), - 5 => TxUpdateReader::new_unchecked(inner).into(), - 6 => TxCompleteReader::new_unchecked(inner).into(), - 7 => TxAbortReader::new_unchecked(inner).into(), - 8 => TxInitRBFReader::new_unchecked(inner).into(), - 9 => TxAckRBFReader::new_unchecked(inner).into(), - 10 => ShutdownReader::new_unchecked(inner).into(), - 11 => ClosingSignedReader::new_unchecked(inner).into(), - 12 => AddTlcReader::new_unchecked(inner).into(), - 13 => TlcsSignedReader::new_unchecked(inner).into(), - 14 => RevokeAndAckReader::new_unchecked(inner).into(), - 15 => RemoveTlcReader::new_unchecked(inner).into(), + 2 => TxSignaturesReader::new_unchecked(inner).into(), + 3 => TxUpdateReader::new_unchecked(inner).into(), + 4 => TxCompleteReader::new_unchecked(inner).into(), + 5 => TxAbortReader::new_unchecked(inner).into(), + 6 => TxInitRBFReader::new_unchecked(inner).into(), + 7 => TxAckRBFReader::new_unchecked(inner).into(), + 8 => CommitmentSignedReader::new_unchecked(inner).into(), + 9 => ChannelReadyReader::new_unchecked(inner).into(), + 10 => AddTlcReader::new_unchecked(inner).into(), + 11 => RemoveTlcReader::new_unchecked(inner).into(), + 12 => RevokeAndAckReader::new_unchecked(inner).into(), + 13 => ShutdownReader::new_unchecked(inner).into(), + 14 => ClosingSignedReader::new_unchecked(inner).into(), + 15 => ReestablishChannelReader::new_unchecked(inner).into(), _ => panic!("{}: invalid data", Self::NAME), } } @@ -9313,20 +9055,20 @@ impl<'r> molecule::prelude::Reader<'r> for CFNMessageReader<'r> { match item_id { 0 => OpenChannelReader::verify(inner_slice, compatible), 1 => AcceptChannelReader::verify(inner_slice, compatible), - 2 => CommitmentSignedReader::verify(inner_slice, compatible), - 3 => TxSignaturesReader::verify(inner_slice, compatible), - 4 => ChannelReadyReader::verify(inner_slice, compatible), - 5 => TxUpdateReader::verify(inner_slice, compatible), - 6 => TxCompleteReader::verify(inner_slice, compatible), - 7 => TxAbortReader::verify(inner_slice, compatible), - 8 => TxInitRBFReader::verify(inner_slice, compatible), - 9 => TxAckRBFReader::verify(inner_slice, compatible), - 10 => ShutdownReader::verify(inner_slice, compatible), - 11 => ClosingSignedReader::verify(inner_slice, compatible), - 12 => AddTlcReader::verify(inner_slice, compatible), - 13 => TlcsSignedReader::verify(inner_slice, compatible), - 14 => RevokeAndAckReader::verify(inner_slice, compatible), - 15 => RemoveTlcReader::verify(inner_slice, compatible), + 2 => TxSignaturesReader::verify(inner_slice, compatible), + 3 => TxUpdateReader::verify(inner_slice, compatible), + 4 => TxCompleteReader::verify(inner_slice, compatible), + 5 => TxAbortReader::verify(inner_slice, compatible), + 6 => TxInitRBFReader::verify(inner_slice, compatible), + 7 => TxAckRBFReader::verify(inner_slice, compatible), + 8 => CommitmentSignedReader::verify(inner_slice, compatible), + 9 => ChannelReadyReader::verify(inner_slice, compatible), + 10 => AddTlcReader::verify(inner_slice, compatible), + 11 => RemoveTlcReader::verify(inner_slice, compatible), + 12 => RevokeAndAckReader::verify(inner_slice, compatible), + 13 => ShutdownReader::verify(inner_slice, compatible), + 14 => ClosingSignedReader::verify(inner_slice, compatible), + 15 => ReestablishChannelReader::verify(inner_slice, compatible), _ => ve!(Self, UnknownItem, Self::ITEMS_COUNT, item_id), }?; Ok(()) @@ -9365,39 +9107,39 @@ impl molecule::prelude::Builder for CFNMessageBuilder { pub enum CFNMessageUnion { OpenChannel(OpenChannel), AcceptChannel(AcceptChannel), - CommitmentSigned(CommitmentSigned), TxSignatures(TxSignatures), - ChannelReady(ChannelReady), TxUpdate(TxUpdate), TxComplete(TxComplete), TxAbort(TxAbort), TxInitRBF(TxInitRBF), TxAckRBF(TxAckRBF), - Shutdown(Shutdown), - ClosingSigned(ClosingSigned), + CommitmentSigned(CommitmentSigned), + ChannelReady(ChannelReady), AddTlc(AddTlc), - TlcsSigned(TlcsSigned), - RevokeAndAck(RevokeAndAck), RemoveTlc(RemoveTlc), + RevokeAndAck(RevokeAndAck), + Shutdown(Shutdown), + ClosingSigned(ClosingSigned), + ReestablishChannel(ReestablishChannel), } #[derive(Debug, Clone, Copy)] pub enum CFNMessageUnionReader<'r> { OpenChannel(OpenChannelReader<'r>), AcceptChannel(AcceptChannelReader<'r>), - CommitmentSigned(CommitmentSignedReader<'r>), TxSignatures(TxSignaturesReader<'r>), - ChannelReady(ChannelReadyReader<'r>), TxUpdate(TxUpdateReader<'r>), TxComplete(TxCompleteReader<'r>), TxAbort(TxAbortReader<'r>), TxInitRBF(TxInitRBFReader<'r>), TxAckRBF(TxAckRBFReader<'r>), - Shutdown(ShutdownReader<'r>), - ClosingSigned(ClosingSignedReader<'r>), + CommitmentSigned(CommitmentSignedReader<'r>), + ChannelReady(ChannelReadyReader<'r>), AddTlc(AddTlcReader<'r>), - TlcsSigned(TlcsSignedReader<'r>), - RevokeAndAck(RevokeAndAckReader<'r>), RemoveTlc(RemoveTlcReader<'r>), + RevokeAndAck(RevokeAndAckReader<'r>), + Shutdown(ShutdownReader<'r>), + ClosingSigned(ClosingSignedReader<'r>), + ReestablishChannel(ReestablishChannelReader<'r>), } impl ::core::default::Default for CFNMessageUnion { fn default() -> Self { @@ -9413,15 +9155,9 @@ impl ::core::fmt::Display for CFNMessageUnion { CFNMessageUnion::AcceptChannel(ref item) => { write!(f, "{}::{}({})", Self::NAME, AcceptChannel::NAME, item) } - CFNMessageUnion::CommitmentSigned(ref item) => { - write!(f, "{}::{}({})", Self::NAME, CommitmentSigned::NAME, item) - } CFNMessageUnion::TxSignatures(ref item) => { write!(f, "{}::{}({})", Self::NAME, TxSignatures::NAME, item) } - CFNMessageUnion::ChannelReady(ref item) => { - write!(f, "{}::{}({})", Self::NAME, ChannelReady::NAME, item) - } CFNMessageUnion::TxUpdate(ref item) => { write!(f, "{}::{}({})", Self::NAME, TxUpdate::NAME, item) } @@ -9437,23 +9173,29 @@ impl ::core::fmt::Display for CFNMessageUnion { CFNMessageUnion::TxAckRBF(ref item) => { write!(f, "{}::{}({})", Self::NAME, TxAckRBF::NAME, item) } - CFNMessageUnion::Shutdown(ref item) => { - write!(f, "{}::{}({})", Self::NAME, Shutdown::NAME, item) + CFNMessageUnion::CommitmentSigned(ref item) => { + write!(f, "{}::{}({})", Self::NAME, CommitmentSigned::NAME, item) } - CFNMessageUnion::ClosingSigned(ref item) => { - write!(f, "{}::{}({})", Self::NAME, ClosingSigned::NAME, item) + CFNMessageUnion::ChannelReady(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ChannelReady::NAME, item) } CFNMessageUnion::AddTlc(ref item) => { write!(f, "{}::{}({})", Self::NAME, AddTlc::NAME, item) } - CFNMessageUnion::TlcsSigned(ref item) => { - write!(f, "{}::{}({})", Self::NAME, TlcsSigned::NAME, item) + CFNMessageUnion::RemoveTlc(ref item) => { + write!(f, "{}::{}({})", Self::NAME, RemoveTlc::NAME, item) } CFNMessageUnion::RevokeAndAck(ref item) => { write!(f, "{}::{}({})", Self::NAME, RevokeAndAck::NAME, item) } - CFNMessageUnion::RemoveTlc(ref item) => { - write!(f, "{}::{}({})", Self::NAME, RemoveTlc::NAME, item) + CFNMessageUnion::Shutdown(ref item) => { + write!(f, "{}::{}({})", Self::NAME, Shutdown::NAME, item) + } + CFNMessageUnion::ClosingSigned(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ClosingSigned::NAME, item) + } + CFNMessageUnion::ReestablishChannel(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ReestablishChannel::NAME, item) } } } @@ -9467,15 +9209,9 @@ impl<'r> ::core::fmt::Display for CFNMessageUnionReader<'r> { CFNMessageUnionReader::AcceptChannel(ref item) => { write!(f, "{}::{}({})", Self::NAME, AcceptChannel::NAME, item) } - CFNMessageUnionReader::CommitmentSigned(ref item) => { - write!(f, "{}::{}({})", Self::NAME, CommitmentSigned::NAME, item) - } CFNMessageUnionReader::TxSignatures(ref item) => { write!(f, "{}::{}({})", Self::NAME, TxSignatures::NAME, item) } - CFNMessageUnionReader::ChannelReady(ref item) => { - write!(f, "{}::{}({})", Self::NAME, ChannelReady::NAME, item) - } CFNMessageUnionReader::TxUpdate(ref item) => { write!(f, "{}::{}({})", Self::NAME, TxUpdate::NAME, item) } @@ -9491,23 +9227,29 @@ impl<'r> ::core::fmt::Display for CFNMessageUnionReader<'r> { CFNMessageUnionReader::TxAckRBF(ref item) => { write!(f, "{}::{}({})", Self::NAME, TxAckRBF::NAME, item) } - CFNMessageUnionReader::Shutdown(ref item) => { - write!(f, "{}::{}({})", Self::NAME, Shutdown::NAME, item) + CFNMessageUnionReader::CommitmentSigned(ref item) => { + write!(f, "{}::{}({})", Self::NAME, CommitmentSigned::NAME, item) } - CFNMessageUnionReader::ClosingSigned(ref item) => { - write!(f, "{}::{}({})", Self::NAME, ClosingSigned::NAME, item) + CFNMessageUnionReader::ChannelReady(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ChannelReady::NAME, item) } CFNMessageUnionReader::AddTlc(ref item) => { write!(f, "{}::{}({})", Self::NAME, AddTlc::NAME, item) } - CFNMessageUnionReader::TlcsSigned(ref item) => { - write!(f, "{}::{}({})", Self::NAME, TlcsSigned::NAME, item) + CFNMessageUnionReader::RemoveTlc(ref item) => { + write!(f, "{}::{}({})", Self::NAME, RemoveTlc::NAME, item) } CFNMessageUnionReader::RevokeAndAck(ref item) => { write!(f, "{}::{}({})", Self::NAME, RevokeAndAck::NAME, item) } - CFNMessageUnionReader::RemoveTlc(ref item) => { - write!(f, "{}::{}({})", Self::NAME, RemoveTlc::NAME, item) + CFNMessageUnionReader::Shutdown(ref item) => { + write!(f, "{}::{}({})", Self::NAME, Shutdown::NAME, item) + } + CFNMessageUnionReader::ClosingSigned(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ClosingSigned::NAME, item) + } + CFNMessageUnionReader::ReestablishChannel(ref item) => { + write!(f, "{}::{}({})", Self::NAME, ReestablishChannel::NAME, item) } } } @@ -9517,20 +9259,20 @@ impl CFNMessageUnion { match self { CFNMessageUnion::OpenChannel(ref item) => write!(f, "{}", item), CFNMessageUnion::AcceptChannel(ref item) => write!(f, "{}", item), - CFNMessageUnion::CommitmentSigned(ref item) => write!(f, "{}", item), CFNMessageUnion::TxSignatures(ref item) => write!(f, "{}", item), - CFNMessageUnion::ChannelReady(ref item) => write!(f, "{}", item), CFNMessageUnion::TxUpdate(ref item) => write!(f, "{}", item), CFNMessageUnion::TxComplete(ref item) => write!(f, "{}", item), CFNMessageUnion::TxAbort(ref item) => write!(f, "{}", item), CFNMessageUnion::TxInitRBF(ref item) => write!(f, "{}", item), CFNMessageUnion::TxAckRBF(ref item) => write!(f, "{}", item), - CFNMessageUnion::Shutdown(ref item) => write!(f, "{}", item), - CFNMessageUnion::ClosingSigned(ref item) => write!(f, "{}", item), + CFNMessageUnion::CommitmentSigned(ref item) => write!(f, "{}", item), + CFNMessageUnion::ChannelReady(ref item) => write!(f, "{}", item), CFNMessageUnion::AddTlc(ref item) => write!(f, "{}", item), - CFNMessageUnion::TlcsSigned(ref item) => write!(f, "{}", item), - CFNMessageUnion::RevokeAndAck(ref item) => write!(f, "{}", item), CFNMessageUnion::RemoveTlc(ref item) => write!(f, "{}", item), + CFNMessageUnion::RevokeAndAck(ref item) => write!(f, "{}", item), + CFNMessageUnion::Shutdown(ref item) => write!(f, "{}", item), + CFNMessageUnion::ClosingSigned(ref item) => write!(f, "{}", item), + CFNMessageUnion::ReestablishChannel(ref item) => write!(f, "{}", item), } } } @@ -9539,20 +9281,20 @@ impl<'r> CFNMessageUnionReader<'r> { match self { CFNMessageUnionReader::OpenChannel(ref item) => write!(f, "{}", item), CFNMessageUnionReader::AcceptChannel(ref item) => write!(f, "{}", item), - CFNMessageUnionReader::CommitmentSigned(ref item) => write!(f, "{}", item), CFNMessageUnionReader::TxSignatures(ref item) => write!(f, "{}", item), - CFNMessageUnionReader::ChannelReady(ref item) => write!(f, "{}", item), CFNMessageUnionReader::TxUpdate(ref item) => write!(f, "{}", item), CFNMessageUnionReader::TxComplete(ref item) => write!(f, "{}", item), CFNMessageUnionReader::TxAbort(ref item) => write!(f, "{}", item), CFNMessageUnionReader::TxInitRBF(ref item) => write!(f, "{}", item), CFNMessageUnionReader::TxAckRBF(ref item) => write!(f, "{}", item), - CFNMessageUnionReader::Shutdown(ref item) => write!(f, "{}", item), - CFNMessageUnionReader::ClosingSigned(ref item) => write!(f, "{}", item), + CFNMessageUnionReader::CommitmentSigned(ref item) => write!(f, "{}", item), + CFNMessageUnionReader::ChannelReady(ref item) => write!(f, "{}", item), CFNMessageUnionReader::AddTlc(ref item) => write!(f, "{}", item), - CFNMessageUnionReader::TlcsSigned(ref item) => write!(f, "{}", item), - CFNMessageUnionReader::RevokeAndAck(ref item) => write!(f, "{}", item), CFNMessageUnionReader::RemoveTlc(ref item) => write!(f, "{}", item), + CFNMessageUnionReader::RevokeAndAck(ref item) => write!(f, "{}", item), + CFNMessageUnionReader::Shutdown(ref item) => write!(f, "{}", item), + CFNMessageUnionReader::ClosingSigned(ref item) => write!(f, "{}", item), + CFNMessageUnionReader::ReestablishChannel(ref item) => write!(f, "{}", item), } } } @@ -9566,21 +9308,11 @@ impl ::core::convert::From for CFNMessageUnion { CFNMessageUnion::AcceptChannel(item) } } -impl ::core::convert::From for CFNMessageUnion { - fn from(item: CommitmentSigned) -> Self { - CFNMessageUnion::CommitmentSigned(item) - } -} impl ::core::convert::From for CFNMessageUnion { fn from(item: TxSignatures) -> Self { CFNMessageUnion::TxSignatures(item) } } -impl ::core::convert::From for CFNMessageUnion { - fn from(item: ChannelReady) -> Self { - CFNMessageUnion::ChannelReady(item) - } -} impl ::core::convert::From for CFNMessageUnion { fn from(item: TxUpdate) -> Self { CFNMessageUnion::TxUpdate(item) @@ -9606,14 +9338,14 @@ impl ::core::convert::From for CFNMessageUnion { CFNMessageUnion::TxAckRBF(item) } } -impl ::core::convert::From for CFNMessageUnion { - fn from(item: Shutdown) -> Self { - CFNMessageUnion::Shutdown(item) +impl ::core::convert::From for CFNMessageUnion { + fn from(item: CommitmentSigned) -> Self { + CFNMessageUnion::CommitmentSigned(item) } } -impl ::core::convert::From for CFNMessageUnion { - fn from(item: ClosingSigned) -> Self { - CFNMessageUnion::ClosingSigned(item) +impl ::core::convert::From for CFNMessageUnion { + fn from(item: ChannelReady) -> Self { + CFNMessageUnion::ChannelReady(item) } } impl ::core::convert::From for CFNMessageUnion { @@ -9621,9 +9353,9 @@ impl ::core::convert::From for CFNMessageUnion { CFNMessageUnion::AddTlc(item) } } -impl ::core::convert::From for CFNMessageUnion { - fn from(item: TlcsSigned) -> Self { - CFNMessageUnion::TlcsSigned(item) +impl ::core::convert::From for CFNMessageUnion { + fn from(item: RemoveTlc) -> Self { + CFNMessageUnion::RemoveTlc(item) } } impl ::core::convert::From for CFNMessageUnion { @@ -9631,9 +9363,19 @@ impl ::core::convert::From for CFNMessageUnion { CFNMessageUnion::RevokeAndAck(item) } } -impl ::core::convert::From for CFNMessageUnion { - fn from(item: RemoveTlc) -> Self { - CFNMessageUnion::RemoveTlc(item) +impl ::core::convert::From for CFNMessageUnion { + fn from(item: Shutdown) -> Self { + CFNMessageUnion::Shutdown(item) + } +} +impl ::core::convert::From for CFNMessageUnion { + fn from(item: ClosingSigned) -> Self { + CFNMessageUnion::ClosingSigned(item) + } +} +impl ::core::convert::From for CFNMessageUnion { + fn from(item: ReestablishChannel) -> Self { + CFNMessageUnion::ReestablishChannel(item) } } impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { @@ -9646,21 +9388,11 @@ impl<'r> ::core::convert::From> for CFNMessageUnionReade CFNMessageUnionReader::AcceptChannel(item) } } -impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { - fn from(item: CommitmentSignedReader<'r>) -> Self { - CFNMessageUnionReader::CommitmentSigned(item) - } -} impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { fn from(item: TxSignaturesReader<'r>) -> Self { CFNMessageUnionReader::TxSignatures(item) } } -impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { - fn from(item: ChannelReadyReader<'r>) -> Self { - CFNMessageUnionReader::ChannelReady(item) - } -} impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { fn from(item: TxUpdateReader<'r>) -> Self { CFNMessageUnionReader::TxUpdate(item) @@ -9686,14 +9418,14 @@ impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> CFNMessageUnionReader::TxAckRBF(item) } } -impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { - fn from(item: ShutdownReader<'r>) -> Self { - CFNMessageUnionReader::Shutdown(item) +impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { + fn from(item: CommitmentSignedReader<'r>) -> Self { + CFNMessageUnionReader::CommitmentSigned(item) } } -impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { - fn from(item: ClosingSignedReader<'r>) -> Self { - CFNMessageUnionReader::ClosingSigned(item) +impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { + fn from(item: ChannelReadyReader<'r>) -> Self { + CFNMessageUnionReader::ChannelReady(item) } } impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { @@ -9701,9 +9433,9 @@ impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { CFNMessageUnionReader::AddTlc(item) } } -impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { - fn from(item: TlcsSignedReader<'r>) -> Self { - CFNMessageUnionReader::TlcsSigned(item) +impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { + fn from(item: RemoveTlcReader<'r>) -> Self { + CFNMessageUnionReader::RemoveTlc(item) } } impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { @@ -9711,9 +9443,19 @@ impl<'r> ::core::convert::From> for CFNMessageUnionReader CFNMessageUnionReader::RevokeAndAck(item) } } -impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { - fn from(item: RemoveTlcReader<'r>) -> Self { - CFNMessageUnionReader::RemoveTlc(item) +impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { + fn from(item: ShutdownReader<'r>) -> Self { + CFNMessageUnionReader::Shutdown(item) + } +} +impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { + fn from(item: ClosingSignedReader<'r>) -> Self { + CFNMessageUnionReader::ClosingSigned(item) + } +} +impl<'r> ::core::convert::From> for CFNMessageUnionReader<'r> { + fn from(item: ReestablishChannelReader<'r>) -> Self { + CFNMessageUnionReader::ReestablishChannel(item) } } impl CFNMessageUnion { @@ -9722,100 +9464,100 @@ impl CFNMessageUnion { match self { CFNMessageUnion::OpenChannel(item) => item.as_bytes(), CFNMessageUnion::AcceptChannel(item) => item.as_bytes(), - CFNMessageUnion::CommitmentSigned(item) => item.as_bytes(), CFNMessageUnion::TxSignatures(item) => item.as_bytes(), - CFNMessageUnion::ChannelReady(item) => item.as_bytes(), CFNMessageUnion::TxUpdate(item) => item.as_bytes(), CFNMessageUnion::TxComplete(item) => item.as_bytes(), CFNMessageUnion::TxAbort(item) => item.as_bytes(), CFNMessageUnion::TxInitRBF(item) => item.as_bytes(), CFNMessageUnion::TxAckRBF(item) => item.as_bytes(), - CFNMessageUnion::Shutdown(item) => item.as_bytes(), - CFNMessageUnion::ClosingSigned(item) => item.as_bytes(), + CFNMessageUnion::CommitmentSigned(item) => item.as_bytes(), + CFNMessageUnion::ChannelReady(item) => item.as_bytes(), CFNMessageUnion::AddTlc(item) => item.as_bytes(), - CFNMessageUnion::TlcsSigned(item) => item.as_bytes(), - CFNMessageUnion::RevokeAndAck(item) => item.as_bytes(), CFNMessageUnion::RemoveTlc(item) => item.as_bytes(), + CFNMessageUnion::RevokeAndAck(item) => item.as_bytes(), + CFNMessageUnion::Shutdown(item) => item.as_bytes(), + CFNMessageUnion::ClosingSigned(item) => item.as_bytes(), + CFNMessageUnion::ReestablishChannel(item) => item.as_bytes(), } } pub fn as_slice(&self) -> &[u8] { match self { CFNMessageUnion::OpenChannel(item) => item.as_slice(), CFNMessageUnion::AcceptChannel(item) => item.as_slice(), - CFNMessageUnion::CommitmentSigned(item) => item.as_slice(), CFNMessageUnion::TxSignatures(item) => item.as_slice(), - CFNMessageUnion::ChannelReady(item) => item.as_slice(), CFNMessageUnion::TxUpdate(item) => item.as_slice(), CFNMessageUnion::TxComplete(item) => item.as_slice(), CFNMessageUnion::TxAbort(item) => item.as_slice(), CFNMessageUnion::TxInitRBF(item) => item.as_slice(), CFNMessageUnion::TxAckRBF(item) => item.as_slice(), - CFNMessageUnion::Shutdown(item) => item.as_slice(), - CFNMessageUnion::ClosingSigned(item) => item.as_slice(), + CFNMessageUnion::CommitmentSigned(item) => item.as_slice(), + CFNMessageUnion::ChannelReady(item) => item.as_slice(), CFNMessageUnion::AddTlc(item) => item.as_slice(), - CFNMessageUnion::TlcsSigned(item) => item.as_slice(), - CFNMessageUnion::RevokeAndAck(item) => item.as_slice(), CFNMessageUnion::RemoveTlc(item) => item.as_slice(), + CFNMessageUnion::RevokeAndAck(item) => item.as_slice(), + CFNMessageUnion::Shutdown(item) => item.as_slice(), + CFNMessageUnion::ClosingSigned(item) => item.as_slice(), + CFNMessageUnion::ReestablishChannel(item) => item.as_slice(), } } pub fn item_id(&self) -> molecule::Number { match self { CFNMessageUnion::OpenChannel(_) => 0, CFNMessageUnion::AcceptChannel(_) => 1, - CFNMessageUnion::CommitmentSigned(_) => 2, - CFNMessageUnion::TxSignatures(_) => 3, - CFNMessageUnion::ChannelReady(_) => 4, - CFNMessageUnion::TxUpdate(_) => 5, - CFNMessageUnion::TxComplete(_) => 6, - CFNMessageUnion::TxAbort(_) => 7, - CFNMessageUnion::TxInitRBF(_) => 8, - CFNMessageUnion::TxAckRBF(_) => 9, - CFNMessageUnion::Shutdown(_) => 10, - CFNMessageUnion::ClosingSigned(_) => 11, - CFNMessageUnion::AddTlc(_) => 12, - CFNMessageUnion::TlcsSigned(_) => 13, - CFNMessageUnion::RevokeAndAck(_) => 14, - CFNMessageUnion::RemoveTlc(_) => 15, + CFNMessageUnion::TxSignatures(_) => 2, + CFNMessageUnion::TxUpdate(_) => 3, + CFNMessageUnion::TxComplete(_) => 4, + CFNMessageUnion::TxAbort(_) => 5, + CFNMessageUnion::TxInitRBF(_) => 6, + CFNMessageUnion::TxAckRBF(_) => 7, + CFNMessageUnion::CommitmentSigned(_) => 8, + CFNMessageUnion::ChannelReady(_) => 9, + CFNMessageUnion::AddTlc(_) => 10, + CFNMessageUnion::RemoveTlc(_) => 11, + CFNMessageUnion::RevokeAndAck(_) => 12, + CFNMessageUnion::Shutdown(_) => 13, + CFNMessageUnion::ClosingSigned(_) => 14, + CFNMessageUnion::ReestablishChannel(_) => 15, } } pub fn item_name(&self) -> &str { match self { CFNMessageUnion::OpenChannel(_) => "OpenChannel", CFNMessageUnion::AcceptChannel(_) => "AcceptChannel", - CFNMessageUnion::CommitmentSigned(_) => "CommitmentSigned", CFNMessageUnion::TxSignatures(_) => "TxSignatures", - CFNMessageUnion::ChannelReady(_) => "ChannelReady", CFNMessageUnion::TxUpdate(_) => "TxUpdate", CFNMessageUnion::TxComplete(_) => "TxComplete", CFNMessageUnion::TxAbort(_) => "TxAbort", CFNMessageUnion::TxInitRBF(_) => "TxInitRBF", CFNMessageUnion::TxAckRBF(_) => "TxAckRBF", - CFNMessageUnion::Shutdown(_) => "Shutdown", - CFNMessageUnion::ClosingSigned(_) => "ClosingSigned", + CFNMessageUnion::CommitmentSigned(_) => "CommitmentSigned", + CFNMessageUnion::ChannelReady(_) => "ChannelReady", CFNMessageUnion::AddTlc(_) => "AddTlc", - CFNMessageUnion::TlcsSigned(_) => "TlcsSigned", - CFNMessageUnion::RevokeAndAck(_) => "RevokeAndAck", CFNMessageUnion::RemoveTlc(_) => "RemoveTlc", + CFNMessageUnion::RevokeAndAck(_) => "RevokeAndAck", + CFNMessageUnion::Shutdown(_) => "Shutdown", + CFNMessageUnion::ClosingSigned(_) => "ClosingSigned", + CFNMessageUnion::ReestablishChannel(_) => "ReestablishChannel", } } pub fn as_reader<'r>(&'r self) -> CFNMessageUnionReader<'r> { match self { CFNMessageUnion::OpenChannel(item) => item.as_reader().into(), CFNMessageUnion::AcceptChannel(item) => item.as_reader().into(), - CFNMessageUnion::CommitmentSigned(item) => item.as_reader().into(), CFNMessageUnion::TxSignatures(item) => item.as_reader().into(), - CFNMessageUnion::ChannelReady(item) => item.as_reader().into(), CFNMessageUnion::TxUpdate(item) => item.as_reader().into(), CFNMessageUnion::TxComplete(item) => item.as_reader().into(), CFNMessageUnion::TxAbort(item) => item.as_reader().into(), CFNMessageUnion::TxInitRBF(item) => item.as_reader().into(), CFNMessageUnion::TxAckRBF(item) => item.as_reader().into(), - CFNMessageUnion::Shutdown(item) => item.as_reader().into(), - CFNMessageUnion::ClosingSigned(item) => item.as_reader().into(), + CFNMessageUnion::CommitmentSigned(item) => item.as_reader().into(), + CFNMessageUnion::ChannelReady(item) => item.as_reader().into(), CFNMessageUnion::AddTlc(item) => item.as_reader().into(), - CFNMessageUnion::TlcsSigned(item) => item.as_reader().into(), - CFNMessageUnion::RevokeAndAck(item) => item.as_reader().into(), CFNMessageUnion::RemoveTlc(item) => item.as_reader().into(), + CFNMessageUnion::RevokeAndAck(item) => item.as_reader().into(), + CFNMessageUnion::Shutdown(item) => item.as_reader().into(), + CFNMessageUnion::ClosingSigned(item) => item.as_reader().into(), + CFNMessageUnion::ReestablishChannel(item) => item.as_reader().into(), } } } @@ -9825,60 +9567,60 @@ impl<'r> CFNMessageUnionReader<'r> { match self { CFNMessageUnionReader::OpenChannel(item) => item.as_slice(), CFNMessageUnionReader::AcceptChannel(item) => item.as_slice(), - CFNMessageUnionReader::CommitmentSigned(item) => item.as_slice(), CFNMessageUnionReader::TxSignatures(item) => item.as_slice(), - CFNMessageUnionReader::ChannelReady(item) => item.as_slice(), CFNMessageUnionReader::TxUpdate(item) => item.as_slice(), CFNMessageUnionReader::TxComplete(item) => item.as_slice(), CFNMessageUnionReader::TxAbort(item) => item.as_slice(), CFNMessageUnionReader::TxInitRBF(item) => item.as_slice(), CFNMessageUnionReader::TxAckRBF(item) => item.as_slice(), - CFNMessageUnionReader::Shutdown(item) => item.as_slice(), - CFNMessageUnionReader::ClosingSigned(item) => item.as_slice(), + CFNMessageUnionReader::CommitmentSigned(item) => item.as_slice(), + CFNMessageUnionReader::ChannelReady(item) => item.as_slice(), CFNMessageUnionReader::AddTlc(item) => item.as_slice(), - CFNMessageUnionReader::TlcsSigned(item) => item.as_slice(), - CFNMessageUnionReader::RevokeAndAck(item) => item.as_slice(), CFNMessageUnionReader::RemoveTlc(item) => item.as_slice(), + CFNMessageUnionReader::RevokeAndAck(item) => item.as_slice(), + CFNMessageUnionReader::Shutdown(item) => item.as_slice(), + CFNMessageUnionReader::ClosingSigned(item) => item.as_slice(), + CFNMessageUnionReader::ReestablishChannel(item) => item.as_slice(), } } pub fn item_id(&self) -> molecule::Number { match self { CFNMessageUnionReader::OpenChannel(_) => 0, CFNMessageUnionReader::AcceptChannel(_) => 1, - CFNMessageUnionReader::CommitmentSigned(_) => 2, - CFNMessageUnionReader::TxSignatures(_) => 3, - CFNMessageUnionReader::ChannelReady(_) => 4, - CFNMessageUnionReader::TxUpdate(_) => 5, - CFNMessageUnionReader::TxComplete(_) => 6, - CFNMessageUnionReader::TxAbort(_) => 7, - CFNMessageUnionReader::TxInitRBF(_) => 8, - CFNMessageUnionReader::TxAckRBF(_) => 9, - CFNMessageUnionReader::Shutdown(_) => 10, - CFNMessageUnionReader::ClosingSigned(_) => 11, - CFNMessageUnionReader::AddTlc(_) => 12, - CFNMessageUnionReader::TlcsSigned(_) => 13, - CFNMessageUnionReader::RevokeAndAck(_) => 14, - CFNMessageUnionReader::RemoveTlc(_) => 15, + CFNMessageUnionReader::TxSignatures(_) => 2, + CFNMessageUnionReader::TxUpdate(_) => 3, + CFNMessageUnionReader::TxComplete(_) => 4, + CFNMessageUnionReader::TxAbort(_) => 5, + CFNMessageUnionReader::TxInitRBF(_) => 6, + CFNMessageUnionReader::TxAckRBF(_) => 7, + CFNMessageUnionReader::CommitmentSigned(_) => 8, + CFNMessageUnionReader::ChannelReady(_) => 9, + CFNMessageUnionReader::AddTlc(_) => 10, + CFNMessageUnionReader::RemoveTlc(_) => 11, + CFNMessageUnionReader::RevokeAndAck(_) => 12, + CFNMessageUnionReader::Shutdown(_) => 13, + CFNMessageUnionReader::ClosingSigned(_) => 14, + CFNMessageUnionReader::ReestablishChannel(_) => 15, } } pub fn item_name(&self) -> &str { match self { CFNMessageUnionReader::OpenChannel(_) => "OpenChannel", CFNMessageUnionReader::AcceptChannel(_) => "AcceptChannel", - CFNMessageUnionReader::CommitmentSigned(_) => "CommitmentSigned", CFNMessageUnionReader::TxSignatures(_) => "TxSignatures", - CFNMessageUnionReader::ChannelReady(_) => "ChannelReady", CFNMessageUnionReader::TxUpdate(_) => "TxUpdate", CFNMessageUnionReader::TxComplete(_) => "TxComplete", CFNMessageUnionReader::TxAbort(_) => "TxAbort", CFNMessageUnionReader::TxInitRBF(_) => "TxInitRBF", CFNMessageUnionReader::TxAckRBF(_) => "TxAckRBF", - CFNMessageUnionReader::Shutdown(_) => "Shutdown", - CFNMessageUnionReader::ClosingSigned(_) => "ClosingSigned", + CFNMessageUnionReader::CommitmentSigned(_) => "CommitmentSigned", + CFNMessageUnionReader::ChannelReady(_) => "ChannelReady", CFNMessageUnionReader::AddTlc(_) => "AddTlc", - CFNMessageUnionReader::TlcsSigned(_) => "TlcsSigned", - CFNMessageUnionReader::RevokeAndAck(_) => "RevokeAndAck", CFNMessageUnionReader::RemoveTlc(_) => "RemoveTlc", + CFNMessageUnionReader::RevokeAndAck(_) => "RevokeAndAck", + CFNMessageUnionReader::Shutdown(_) => "Shutdown", + CFNMessageUnionReader::ClosingSigned(_) => "ClosingSigned", + CFNMessageUnionReader::ReestablishChannel(_) => "ReestablishChannel", } } } @@ -9892,21 +9634,11 @@ impl From for CFNMessage { Self::new_builder().set(value).build() } } -impl From for CFNMessage { - fn from(value: CommitmentSigned) -> Self { - Self::new_builder().set(value).build() - } -} impl From for CFNMessage { fn from(value: TxSignatures) -> Self { Self::new_builder().set(value).build() } } -impl From for CFNMessage { - fn from(value: ChannelReady) -> Self { - Self::new_builder().set(value).build() - } -} impl From for CFNMessage { fn from(value: TxUpdate) -> Self { Self::new_builder().set(value).build() @@ -9932,13 +9664,13 @@ impl From for CFNMessage { Self::new_builder().set(value).build() } } -impl From for CFNMessage { - fn from(value: Shutdown) -> Self { +impl From for CFNMessage { + fn from(value: CommitmentSigned) -> Self { Self::new_builder().set(value).build() } } -impl From for CFNMessage { - fn from(value: ClosingSigned) -> Self { +impl From for CFNMessage { + fn from(value: ChannelReady) -> Self { Self::new_builder().set(value).build() } } @@ -9947,8 +9679,8 @@ impl From for CFNMessage { Self::new_builder().set(value).build() } } -impl From for CFNMessage { - fn from(value: TlcsSigned) -> Self { +impl From for CFNMessage { + fn from(value: RemoveTlc) -> Self { Self::new_builder().set(value).build() } } @@ -9957,8 +9689,18 @@ impl From for CFNMessage { Self::new_builder().set(value).build() } } -impl From for CFNMessage { - fn from(value: RemoveTlc) -> Self { +impl From for CFNMessage { + fn from(value: Shutdown) -> Self { + Self::new_builder().set(value).build() + } +} +impl From for CFNMessage { + fn from(value: ClosingSigned) -> Self { + Self::new_builder().set(value).build() + } +} +impl From for CFNMessage { + fn from(value: ReestablishChannel) -> Self { Self::new_builder().set(value).build() } } diff --git a/src/ckb/network.rs b/src/ckb/network.rs index 57190f9d3..c9081aa5b 100644 --- a/src/ckb/network.rs +++ b/src/ckb/network.rs @@ -457,14 +457,21 @@ where "Channel ({:?}) to peer {:?} is already closed. Closing transaction {:?} can be broacasted now.", channel_id, peer_id, tx ); - call_t!( + match call_t!( self.chain_actor, CkbChainMessage::SendTx, DEFAULT_CHAIN_ACTOR_TIMEOUT, tx.clone() ) .expect(ASSUME_CHAIN_ACTOR_ALWAYS_ALIVE_FOR_NOW) - .expect("valid closing tx"); + { + Ok(_) => { + info!("Closing transaction sent to the network: {:?}", tx); + } + Err(err) => { + error!("Failed to send closing transaction to the network: {}", err); + } + } // Notify outside observers. myself diff --git a/src/ckb/schema/cfn.mol b/src/ckb/schema/cfn.mol index 923e3488e..ce7f9e1f5 100644 --- a/src/ckb/schema/cfn.mol +++ b/src/ckb/schema/cfn.mol @@ -3,7 +3,6 @@ import blockchain; array Signature [byte; 64]; array PubNonce [byte; 66]; // PubNonce used by musig2 crate. array Pubkey [byte; 33]; -vector SignatureVec ; table OpenChannel { chain_hash: Byte32, @@ -104,12 +103,6 @@ table AddTlc { expiry: Uint64, } -table TlcsSigned { - channel_id: Byte32, - signature: Signature, - tlc_signatures: SignatureVec, -} - table RevokeAndAck { channel_id: Byte32, per_commitment_secret: Byte32, @@ -135,21 +128,27 @@ table RemoveTlc { reason: RemoveTlcReason, } +table ReestablishChannel { + channel_id: Byte32, + local_commitment_number: Uint64, + remote_commitment_number: Uint64, +} + union CFNMessage { OpenChannel, AcceptChannel, - CommitmentSigned, TxSignatures, - ChannelReady, TxUpdate, TxComplete, TxAbort, TxInitRBF, TxAckRBF, - Shutdown, - ClosingSigned, + CommitmentSigned, + ChannelReady, AddTlc, - TlcsSigned, - RevokeAndAck, RemoveTlc, + RevokeAndAck, + Shutdown, + ClosingSigned, + ReestablishChannel, } diff --git a/src/ckb/types.rs b/src/ckb/types.rs index cca63bea8..9804ea59a 100644 --- a/src/ckb/types.rs +++ b/src/ckb/types.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use super::gen::cfn::{self as molecule_cfn, PubNonce as Byte66, SignatureVec}; +use super::gen::cfn::{self as molecule_cfn, PubNonce as Byte66}; use super::serde_utils::SliceHex; use anyhow::anyhow; use ckb_sdk::{Since, SinceType}; @@ -149,6 +149,18 @@ impl From<&Privkey> for Scalar { } } +impl From<[u8; 32]> for Privkey { + fn from(k: [u8; 32]) -> Self { + Privkey(SecretKey::from_slice(&k).expect("Invalid secret key")) + } +} + +impl From for Privkey { + fn from(scalar: Scalar) -> Self { + scalar.serialize().into() + } +} + impl From for Privkey { fn from(hash: Hash256) -> Self { let mut bytes = [0u8; 32]; @@ -286,6 +298,14 @@ impl Privkey { pub fn pubkey(&self) -> Pubkey { Pubkey::from(self.0.public_key(secp256k1_instance())) } + + pub fn tweak>(&self, scalar: I) -> Self { + let scalar = scalar.into(); + let scalar = Scalar::from_slice(&scalar) + .expect(format!("Value {:?} must be within secp256k1 scalar range. If you generated this value from hash function, then your hash function is busted.", &scalar).as_str()); + let sk = Scalar::from(self); + (scalar + sk).unwrap().into() + } } #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -331,6 +351,14 @@ impl Pubkey { pub fn serialize(&self) -> [u8; 33] { PublicKey::from(self).serialize() } + + pub fn tweak>(&self, scalar: I) -> Self { + let scalar = scalar.into(); + let scalar = Scalar::from_slice(&scalar) + .expect(format!("Value {:?} must be within secp256k1 scalar range. If you generated this value from hash function, then your hash function is busted.", &scalar).as_str()); + let result = Point::from(self) + scalar.base_point_mul(); + PublicKey::from(result.unwrap()).into() + } } #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize, Debug)] @@ -927,49 +955,6 @@ impl TryFrom for AddTlc { } } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TlcsSigned { - pub channel_id: Hash256, - pub signature: Signature, - pub tlc_signatures: Vec, -} - -impl From for molecule_cfn::TlcsSigned { - fn from(tlcs_signed: TlcsSigned) -> Self { - molecule_cfn::TlcsSigned::new_builder() - .channel_id(tlcs_signed.channel_id.into()) - .signature(tlcs_signed.signature.into()) - .tlc_signatures( - SignatureVec::new_builder() - .set( - tlcs_signed - .tlc_signatures - .into_iter() - .map(|tlc_signature| tlc_signature.into()) - .collect(), - ) - .build(), - ) - .build() - } -} - -impl TryFrom for TlcsSigned { - type Error = Error; - - fn try_from(tlcs_signed: molecule_cfn::TlcsSigned) -> Result { - Ok(TlcsSigned { - channel_id: tlcs_signed.channel_id().into(), - signature: tlcs_signed.signature().try_into()?, - tlc_signatures: tlcs_signed - .tlc_signatures() - .into_iter() - .map(|tlc_signature| tlc_signature.try_into()) - .collect::, Error>>()?, - }) - } -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RevokeAndAck { pub channel_id: Hash256, @@ -1120,6 +1105,37 @@ impl TryFrom for RemoveTlc { } } +#[derive(Debug, Clone)] +pub struct ReestablishChannel { + pub channel_id: Hash256, + pub local_commitment_number: u64, + pub remote_commitment_number: u64, +} + +impl From for molecule_cfn::ReestablishChannel { + fn from(reestablish_channel: ReestablishChannel) -> Self { + molecule_cfn::ReestablishChannel::new_builder() + .channel_id(reestablish_channel.channel_id.into()) + .local_commitment_number(reestablish_channel.local_commitment_number.pack()) + .remote_commitment_number(reestablish_channel.remote_commitment_number.pack()) + .build() + } +} + +impl TryFrom for ReestablishChannel { + type Error = Error; + + fn try_from( + reestablish_channel: molecule_cfn::ReestablishChannel, + ) -> Result { + Ok(ReestablishChannel { + channel_id: reestablish_channel.channel_id().into(), + local_commitment_number: reestablish_channel.local_commitment_number().unpack(), + remote_commitment_number: reestablish_channel.remote_commitment_number().unpack(), + }) + } +} + #[derive(Debug, Clone)] pub enum CFNMessage { OpenChannel(OpenChannel), @@ -1135,9 +1151,9 @@ pub enum CFNMessage { Shutdown(Shutdown), ClosingSigned(ClosingSigned), AddTlc(AddTlc), - TlcsSigned(TlcsSigned), RevokeAndAck(RevokeAndAck), RemoveTlc(RemoveTlc), + ReestablishChannel(ReestablishChannel), } impl CFNMessage { @@ -1156,9 +1172,9 @@ impl CFNMessage { CFNMessage::Shutdown(shutdown) => shutdown.channel_id, CFNMessage::ClosingSigned(closing_signed) => closing_signed.channel_id, CFNMessage::AddTlc(add_tlc) => add_tlc.channel_id, - CFNMessage::TlcsSigned(tlcs_signed) => tlcs_signed.channel_id, CFNMessage::RevokeAndAck(revoke_and_ack) => revoke_and_ack.channel_id, CFNMessage::RemoveTlc(remove_tlc) => remove_tlc.channel_id, + CFNMessage::ReestablishChannel(reestablish_channel) => reestablish_channel.channel_id, } } } @@ -1209,8 +1225,8 @@ impl From for molecule_cfn::CFNMessageUnion { CFNMessage::RevokeAndAck(revoke_and_ack) => { molecule_cfn::CFNMessageUnion::RevokeAndAck(revoke_and_ack.into()) } - CFNMessage::TlcsSigned(tlcs_signed) => { - molecule_cfn::CFNMessageUnion::TlcsSigned(tlcs_signed.into()) + CFNMessage::ReestablishChannel(reestablish_channel) => { + molecule_cfn::CFNMessageUnion::ReestablishChannel(reestablish_channel.into()) } } } @@ -1271,12 +1287,12 @@ impl TryFrom for CFNMessage { molecule_cfn::CFNMessageUnion::RemoveTlc(remove_tlc) => { CFNMessage::RemoveTlc(remove_tlc.try_into()?) } - molecule_cfn::CFNMessageUnion::TlcsSigned(tlcs_signed) => { - CFNMessage::TlcsSigned(tlcs_signed.try_into()?) - } molecule_cfn::CFNMessageUnion::RevokeAndAck(revoke_and_ack) => { CFNMessage::RevokeAndAck(revoke_and_ack.try_into()?) } + molecule_cfn::CFNMessageUnion::ReestablishChannel(reestablish_channel) => { + CFNMessage::ReestablishChannel(reestablish_channel.try_into()?) + } }) } } @@ -1299,22 +1315,6 @@ macro_rules! impl_traits { }; } -impl_traits!(OpenChannel); -impl_traits!(AcceptChannel); -impl_traits!(CommitmentSigned); -impl_traits!(TxSignatures); -impl_traits!(ChannelReady); -impl_traits!(TxUpdate); -impl_traits!(TxComplete); -impl_traits!(TxAbort); -impl_traits!(TxInitRBF); -impl_traits!(TxAckRBF); -impl_traits!(Shutdown); -impl_traits!(ClosingSigned); -impl_traits!(AddTlc); -impl_traits!(TlcsSigned); -impl_traits!(RevokeAndAck); -impl_traits!(RemoveTlc); impl_traits!(CFNMessage); #[cfg(test)] diff --git a/src/rpc/channel.rs b/src/rpc/channel.rs index 22ea72a9d..b6d80932d 100644 --- a/src/rpc/channel.rs +++ b/src/rpc/channel.rs @@ -284,7 +284,6 @@ where }, )) }; - handle_actor_call!(self.actor, message, params).map(|response| AddTlcResult { tlc_id: response.tlc_id, }) diff --git a/tests/bruno/e2e/reestablish/01-connect-peer.bru b/tests/bruno/e2e/reestablish/01-connect-peer.bru new file mode 100644 index 000000000..196fd5483 --- /dev/null +++ b/tests/bruno/e2e/reestablish/01-connect-peer.bru @@ -0,0 +1,38 @@ +meta { + name: connect peer + type: http + seq: 1 +} + +post { + url: {{NODE3_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "connect_peer", + "params": [ + {"address": "{{NODE1_ADDR}}"} + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result: isNull +} + +script:post-response { + // Dialing a peer is async in tentacle. Sleep for some time to make sure + // we're connected to the peer. + await new Promise(r => setTimeout(r, 1000)); +} diff --git a/tests/bruno/e2e/reestablish/02-open-channel.bru b/tests/bruno/e2e/reestablish/02-open-channel.bru new file mode 100644 index 000000000..9ddbbe7de --- /dev/null +++ b/tests/bruno/e2e/reestablish/02-open-channel.bru @@ -0,0 +1,39 @@ +meta { + name: Node3 open a channel to Node1 + type: http + seq: 2 +} + +post { + url: {{NODE3_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "open_channel", + "params": [ + { + "peer_id": "{{NODE1_PEERID}}", + "funding_amount": "0xba43b7400" + } + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result.temporary_channel_id: isDefined +} + +script:post-response { + await new Promise(r => setTimeout(r, 2000)); +} diff --git a/tests/bruno/e2e/reestablish/03-get-auto-accepted-channel.bru b/tests/bruno/e2e/reestablish/03-get-auto-accepted-channel.bru new file mode 100644 index 000000000..eaf76c579 --- /dev/null +++ b/tests/bruno/e2e/reestablish/03-get-auto-accepted-channel.bru @@ -0,0 +1,41 @@ +meta { + name: get auto accepted channel id from Node1 + type: http + seq: 3 +} + +post { + url: {{NODE1_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "list_channels", + "params": [ + { + "peer_id": "{{NODE3_PEERID}}" + } + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result.channels: isDefined +} + +script:post-response { + console.log(res.body.result); + // Sleep for sometime to make sure current operation finishes before next request starts. + await new Promise(r => setTimeout(r, 2000)); + bru.setVar("CHANNEL_ID", res.body.result.channels[0].channel_id); +} diff --git a/tests/bruno/e2e/reestablish/06-generate-a-few-blocks.bru b/tests/bruno/e2e/reestablish/06-generate-a-few-blocks.bru new file mode 100644 index 000000000..bf1fb8759 --- /dev/null +++ b/tests/bruno/e2e/reestablish/06-generate-a-few-blocks.bru @@ -0,0 +1,56 @@ +meta { + name: generate a few blocks + type: http + seq: 6 +} + +post { + url: {{CKB_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": {{iteration}}, + "jsonrpc": "2.0", + "method": "generate_block", + "params": [] + } +} + +vars:post-response { + max_iterations: 10 +} + +assert { + res.status: eq 200 +} + +script:pre-request { + // Script taken from https://github.com/usebruno/bruno/discussions/385#discussioncomment-8015350 + // This does not seem to work. + if(bru.getVar("iteration") === undefined){ + console.log("Started generating blocks..."); + bru.setVar("iteration", 0); + } +} + +script:post-response { + if(bru.getVar("iteration") < bru.getVar("max_iterations") -1){ + bru.setVar("iteration", bru.getVar("iteration") + 1); + // This is the name of this bruno file, set this to continue generating blocks. + bru.setNextRequest("generate a few blocks"); + } else { + console.log("Stopping generating blocks"); + // Don't know why it takes so long for funding transaction to be confirmed. + await new Promise(r => setTimeout(r, 5000)); + } + await new Promise(r => setTimeout(r, 10)); + console.log("Generated the " + bru.getVar("iteration") + "th block"); +} diff --git a/tests/bruno/e2e/reestablish/07-add-tlc-from-NODE3.bru b/tests/bruno/e2e/reestablish/07-add-tlc-from-NODE3.bru new file mode 100644 index 000000000..e0784b12a --- /dev/null +++ b/tests/bruno/e2e/reestablish/07-add-tlc-from-NODE3.bru @@ -0,0 +1,41 @@ +meta { + name: add tlc from NODE3 + type: http + seq: 7 +} + +post { + url: {{NODE3_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "add_tlc", + "params": [ + { + "channel_id": "{{CHANNEL_ID}}", + "amount": "0x5f5e100", + "payment_hash": "0x266cec97cbede2cfbce73666f08deed9560bdf7841a7a5a51b3a3f09da249e21", + "expiry": 40 + } + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result.tlc_id: isDefined +} + +script:post-response { + bru.setVar("TLC_ID1", res.body.result.tlc_id); +} diff --git a/tests/bruno/e2e/reestablish/08-disconnect-NODE1.bru b/tests/bruno/e2e/reestablish/08-disconnect-NODE1.bru new file mode 100644 index 000000000..0cbdc312b --- /dev/null +++ b/tests/bruno/e2e/reestablish/08-disconnect-NODE1.bru @@ -0,0 +1,37 @@ +meta { + name: disconnect NODE3 from NODE1 + type: http + seq: 8 +} + +post { + url: {{NODE1_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "disconnect_peer", + "params": [ + {"peer_id": "{{NODE3_PEERID}}"} + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result: isDefined +} + +script:post-response { + // Sleep for sometime to make sure current operation finishes before next request starts. + await new Promise(r => setTimeout(r, 1000)); +} diff --git a/tests/bruno/e2e/reestablish/09-reconnect-peer-NODE1.bru b/tests/bruno/e2e/reestablish/09-reconnect-peer-NODE1.bru new file mode 100644 index 000000000..f1d2902fb --- /dev/null +++ b/tests/bruno/e2e/reestablish/09-reconnect-peer-NODE1.bru @@ -0,0 +1,38 @@ +meta { + name: reconnect peer NODE3 + type: http + seq: 9 +} + +post { + url: {{NODE1_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "connect_peer", + "params": [ + {"address": "{{NODE3_ADDR}}"} + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result: isNull +} + +script:post-response { + // Dialing a peer is async in tentacle. Sleep for some time to make sure + // we're connected to the peer. + await new Promise(r => setTimeout(r, 1000)); +} diff --git a/tests/bruno/e2e/reestablish/15-shutdown-from-NODE1.bru b/tests/bruno/e2e/reestablish/15-shutdown-from-NODE1.bru new file mode 100644 index 000000000..7148cc43b --- /dev/null +++ b/tests/bruno/e2e/reestablish/15-shutdown-from-NODE1.bru @@ -0,0 +1,45 @@ +meta { + name: send shutdown from NODE1 + type: http + seq: 15 +} + +post { + url: {{NODE1_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "shutdown_channel", + "params": [ + { + "channel_id": "{{CHANNEL_ID}}", + "close_script": { + "code_hash": "0x2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a", + "hash_type": "data", + "args": "0x0101010101010101010101010101010101010101" + }, + "fee": "0x0" + } + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result: isNull +} + +script:post-response { + // Sleep for sometime to make sure current operation finishes before next request starts. + await new Promise(r => setTimeout(r, 100)); +} diff --git a/tests/bruno/e2e/reestablish/16-shutdown-from-NODE3.bru b/tests/bruno/e2e/reestablish/16-shutdown-from-NODE3.bru new file mode 100644 index 000000000..6a43beb16 --- /dev/null +++ b/tests/bruno/e2e/reestablish/16-shutdown-from-NODE3.bru @@ -0,0 +1,45 @@ +meta { + name: send shutdown from NODE3 + type: http + seq: 16 +} + +post { + url: {{NODE3_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "shutdown_channel", + "params": [ + { + "channel_id": "{{CHANNEL_ID}}", + "close_script": { + "code_hash": "0x2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a", + "hash_type": "data", + "args": "0x0202020202020202020202020202020202020202" + }, + "fee": "0xbebc200" + } + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result: isNull +} + +script:post-response { + // Sleep for sometime to make sure current operation finishes before next request starts. + await new Promise(r => setTimeout(r, 100)); +} diff --git a/tests/bruno/e2e/reestablish/17-remove-tlc-from-NODE1.bru b/tests/bruno/e2e/reestablish/17-remove-tlc-from-NODE1.bru new file mode 100644 index 000000000..629322ef3 --- /dev/null +++ b/tests/bruno/e2e/reestablish/17-remove-tlc-from-NODE1.bru @@ -0,0 +1,43 @@ +meta { + name: remove tlc from NODE1 + type: http + seq: 17 +} + +post { + url: {{NODE1_RPC_URL}} + body: json + auth: none +} + +headers { + Content-Type: application/json + Accept: application/json +} + +body:json { + { + "id": "42", + "jsonrpc": "2.0", + "method": "remove_tlc", + "params": [ + { + "channel_id": "{{CHANNEL_ID}}", + "tlc_id": "{{TLC_ID1}}", + "reason": { + "error_code": "0x2a" + } + } + ] + } +} + +assert { + res.body.error: isUndefined + res.body.result: isNull +} + +script:post-response { + // Sleep for sometime to make sure current operation finishes before next request starts. + await new Promise(r => setTimeout(r, 100)); +}