Skip to content

Commit 499d84c

Browse files
committed
Merge pull request #920 from TheBlueMatt/2021-05-tlv-ser
Rebroadcast channel_announcements when we broadcast a node_announce
2 parents f8450a7 + bdb2d22 commit 499d84c

File tree

14 files changed

+415
-112
lines changed

14 files changed

+415
-112
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,12 @@ jobs:
144144
uses: actions/cache@v2
145145
with:
146146
path: lightning/net_graph-2021-02-12.bin
147-
key: net_graph-2021-02-12
147+
key: ldk-net_graph-05f0c5a0d772-2020-02-12.bin
148148
- name: Fetch routing graph snapshot
149149
if: steps.cache-graph.outputs.cache-hit != 'true'
150150
run: |
151-
wget -O lightning/net_graph-2021-02-12.bin https://bitcoin.ninja/ldk-net_graph-879e309c128-2020-02-12.bin
152-
if [ "$(sha256sum lightning/net_graph-2021-02-12.bin | awk '{ print $1 }')" != "890a1f80dfb6ef674a1e4ff0f23cd73d740731c395f99d85abbede0cfbb701ab" ]; then
151+
wget -O lightning/net_graph-2021-02-12.bin https://bitcoin.ninja/ldk-net_graph-05f0c5a0d772-2020-02-12.bin
152+
if [ "$(sha256sum lightning/net_graph-2021-02-12.bin | awk '{ print $1 }')" != "7116fca78551fedc714a604cec0ad1ca66caa77bb4d0051290258e7a10e0c6e7" ]; then
153153
echo "Bad hash"
154154
exit 1
155155
fi

CONTRIBUTING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ rustup component add clippy
113113
cargo clippy
114114
```
115115

116+
Significant structures that users persist should always have their serialization methods (usually
117+
`Writeable::write` and `ReadableArgs::read`) begin with
118+
`write_ver_prefix!()`/`read_ver_prefix!()` calls, and end with calls to
119+
`write_tlv_fields!()`/`read_tlv_fields!()`.
120+
121+
Updates to the serialized format which has implications for backwards or forwards compatibility
122+
must be included in release notes.
123+
116124
Security
117125
--------
118126

lightning/src/chain/channelmonitor.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -502,9 +502,6 @@ enum OnchainEvent {
502502
},
503503
}
504504

505-
const SERIALIZATION_VERSION: u8 = 1;
506-
const MIN_SERIALIZATION_VERSION: u8 = 1;
507-
508505
#[cfg_attr(any(test, feature = "fuzztarget", feature = "_test_utils"), derive(PartialEq))]
509506
#[derive(Clone)]
510507
pub(crate) enum ChannelMonitorUpdateStep {
@@ -805,17 +802,17 @@ impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
805802

806803
impl<Signer: Sign> Writeable for ChannelMonitor<Signer> {
807804
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
808-
//TODO: We still write out all the serialization here manually instead of using the fancy
809-
//serialization framework we have, we should migrate things over to it.
810-
writer.write_all(&[SERIALIZATION_VERSION; 1])?;
811-
writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
812-
813805
self.inner.lock().unwrap().write(writer)
814806
}
815807
}
816808

809+
const SERIALIZATION_VERSION: u8 = 1;
810+
const MIN_SERIALIZATION_VERSION: u8 = 1;
811+
817812
impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
818813
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
814+
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
815+
819816
self.latest_update_id.write(writer)?;
820817

821818
// Set in initial Channel-object creation, so should always be set by now:
@@ -991,6 +988,8 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
991988
self.lockdown_from_offchain.write(writer)?;
992989
self.holder_tx_signed.write(writer)?;
993990

991+
write_tlv_fields!(writer, {}, {});
992+
994993
Ok(())
995994
}
996995
}
@@ -2754,11 +2753,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
27542753
}
27552754
}
27562755

2757-
let _ver: u8 = Readable::read(reader)?;
2758-
let min_ver: u8 = Readable::read(reader)?;
2759-
if min_ver > SERIALIZATION_VERSION {
2760-
return Err(DecodeError::UnknownVersion);
2761-
}
2756+
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
27622757

27632758
let latest_update_id: u64 = Readable::read(reader)?;
27642759
let commitment_transaction_number_obscure_factor = <U48 as Readable>::read(reader)?.0;
@@ -2979,6 +2974,8 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
29792974
let lockdown_from_offchain = Readable::read(reader)?;
29802975
let holder_tx_signed = Readable::read(reader)?;
29812976

2977+
read_tlv_fields!(reader, {}, {});
2978+
29822979
let mut secp_ctx = Secp256k1::new();
29832980
secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
29842981

lightning/src/chain/keysinterface.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,10 +704,15 @@ impl BaseSign for InMemorySigner {
704704
}
705705
}
706706

707+
const SERIALIZATION_VERSION: u8 = 1;
708+
const MIN_SERIALIZATION_VERSION: u8 = 1;
709+
707710
impl Sign for InMemorySigner {}
708711

709712
impl Writeable for InMemorySigner {
710713
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
714+
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
715+
711716
self.funding_key.write(writer)?;
712717
self.revocation_base_key.write(writer)?;
713718
self.payment_key.write(writer)?;
@@ -718,12 +723,16 @@ impl Writeable for InMemorySigner {
718723
self.channel_value_satoshis.write(writer)?;
719724
self.channel_keys_id.write(writer)?;
720725

726+
write_tlv_fields!(writer, {}, {});
727+
721728
Ok(())
722729
}
723730
}
724731

725732
impl Readable for InMemorySigner {
726733
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
734+
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
735+
727736
let funding_key = Readable::read(reader)?;
728737
let revocation_base_key = Readable::read(reader)?;
729738
let payment_key = Readable::read(reader)?;
@@ -739,6 +748,8 @@ impl Readable for InMemorySigner {
739748
&htlc_base_key);
740749
let keys_id = Readable::read(reader)?;
741750

751+
read_tlv_fields!(reader, {}, {});
752+
742753
Ok(InMemorySigner {
743754
funding_key,
744755
revocation_base_key,

lightning/src/ln/channel.rs

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use bitcoin::consensus::encode;
1515

1616
use bitcoin::hashes::Hash;
1717
use bitcoin::hashes::sha256::Hash as Sha256;
18+
use bitcoin::hashes::sha256d::Hash as Sha256d;
1819
use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
1920

2021
use bitcoin::secp256k1::key::{PublicKey,SecretKey};
@@ -420,6 +421,10 @@ pub(super) struct Channel<Signer: Sign> {
420421

421422
channel_update_status: ChannelUpdateStatus,
422423

424+
/// Our counterparty's channel_announcement signatures provided in announcement_signatures.
425+
/// This can be used to rebroadcast the channel_announcement message later.
426+
announcement_sigs: Option<(Signature, Signature)>,
427+
423428
// We save these values so we can make sure `next_local_commit_tx_fee_msat` and
424429
// `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
425430
// be, by comparing the cached values to the fee of the tranaction generated by
@@ -621,6 +626,8 @@ impl<Signer: Sign> Channel<Signer> {
621626

622627
channel_update_status: ChannelUpdateStatus::Enabled,
623628

629+
announcement_sigs: None,
630+
624631
#[cfg(any(test, feature = "fuzztarget"))]
625632
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
626633
#[cfg(any(test, feature = "fuzztarget"))]
@@ -862,6 +869,8 @@ impl<Signer: Sign> Channel<Signer> {
862869

863870
channel_update_status: ChannelUpdateStatus::Enabled,
864871

872+
announcement_sigs: None,
873+
865874
#[cfg(any(test, feature = "fuzztarget"))]
866875
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
867876
#[cfg(any(test, feature = "fuzztarget"))]
@@ -3822,6 +3831,8 @@ impl<Signer: Sign> Channel<Signer> {
38223831
/// closing).
38233832
/// Note that the "channel must be funded" requirement is stricter than BOLT 7 requires - see
38243833
/// https://github.com/lightningnetwork/lightning-rfc/issues/468
3834+
///
3835+
/// This will only return ChannelError::Ignore upon failure.
38253836
pub fn get_channel_announcement(&self, node_id: PublicKey, chain_hash: BlockHash) -> Result<(msgs::UnsignedChannelAnnouncement, Signature), ChannelError> {
38263837
if !self.config.announced_channel {
38273838
return Err(ChannelError::Ignore("Channel is not available for public announcements".to_owned()));
@@ -3852,6 +3863,63 @@ impl<Signer: Sign> Channel<Signer> {
38523863
Ok((msg, sig))
38533864
}
38543865

3866+
/// Signs the given channel announcement, returning a ChannelError::Ignore if no keys are
3867+
/// available.
3868+
fn sign_channel_announcement(&self, our_node_secret: &SecretKey, our_node_id: PublicKey, msghash: secp256k1::Message, announcement: msgs::UnsignedChannelAnnouncement, our_bitcoin_sig: Signature) -> Result<msgs::ChannelAnnouncement, ChannelError> {
3869+
if let Some((their_node_sig, their_bitcoin_sig)) = self.announcement_sigs {
3870+
let were_node_one = announcement.node_id_1 == our_node_id;
3871+
3872+
let our_node_sig = self.secp_ctx.sign(&msghash, our_node_secret);
3873+
Ok(msgs::ChannelAnnouncement {
3874+
node_signature_1: if were_node_one { our_node_sig } else { their_node_sig },
3875+
node_signature_2: if were_node_one { their_node_sig } else { our_node_sig },
3876+
bitcoin_signature_1: if were_node_one { our_bitcoin_sig } else { their_bitcoin_sig },
3877+
bitcoin_signature_2: if were_node_one { their_bitcoin_sig } else { our_bitcoin_sig },
3878+
contents: announcement,
3879+
})
3880+
} else {
3881+
Err(ChannelError::Ignore("Attempted to sign channel announcement before we'd received announcement_signatures".to_string()))
3882+
}
3883+
}
3884+
3885+
/// Processes an incoming announcement_signatures message, providing a fully-signed
3886+
/// channel_announcement message which we can broadcast and storing our counterparty's
3887+
/// signatures for later reconstruction/rebroadcast of the channel_announcement.
3888+
pub fn announcement_signatures(&mut self, our_node_secret: &SecretKey, our_node_id: PublicKey, chain_hash: BlockHash, msg: &msgs::AnnouncementSignatures) -> Result<msgs::ChannelAnnouncement, ChannelError> {
3889+
let (announcement, our_bitcoin_sig) = self.get_channel_announcement(our_node_id.clone(), chain_hash)?;
3890+
3891+
let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]);
3892+
3893+
if self.secp_ctx.verify(&msghash, &msg.node_signature, &self.get_counterparty_node_id()).is_err() {
3894+
return Err(ChannelError::Close(format!(
3895+
"Bad announcement_signatures. Failed to verify node_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_node_key is {:?}",
3896+
&announcement, self.get_counterparty_node_id())));
3897+
}
3898+
if self.secp_ctx.verify(&msghash, &msg.bitcoin_signature, self.counterparty_funding_pubkey()).is_err() {
3899+
return Err(ChannelError::Close(format!(
3900+
"Bad announcement_signatures. Failed to verify bitcoin_signature. UnsignedChannelAnnouncement used for verification is {:?}. their_bitcoin_key is ({:?})",
3901+
&announcement, self.counterparty_funding_pubkey())));
3902+
}
3903+
3904+
self.announcement_sigs = Some((msg.node_signature, msg.bitcoin_signature));
3905+
3906+
self.sign_channel_announcement(our_node_secret, our_node_id, msghash, announcement, our_bitcoin_sig)
3907+
}
3908+
3909+
/// Gets a signed channel_announcement for this channel, if we previously received an
3910+
/// announcement_signatures from our counterparty.
3911+
pub fn get_signed_channel_announcement(&self, our_node_secret: &SecretKey, our_node_id: PublicKey, chain_hash: BlockHash) -> Option<msgs::ChannelAnnouncement> {
3912+
let (announcement, our_bitcoin_sig) = match self.get_channel_announcement(our_node_id.clone(), chain_hash) {
3913+
Ok(res) => res,
3914+
Err(_) => return None,
3915+
};
3916+
let msghash = hash_to_message!(&Sha256d::hash(&announcement.encode()[..])[..]);
3917+
match self.sign_channel_announcement(our_node_secret, our_node_id, msghash, announcement, our_bitcoin_sig) {
3918+
Ok(res) => Some(res),
3919+
Err(_) => None,
3920+
}
3921+
}
3922+
38553923
/// May panic if called on a channel that wasn't immediately-previously
38563924
/// self.remove_uncommitted_htlcs_and_mark_paused()'d
38573925
pub fn get_channel_reestablish<L: Deref>(&self, logger: &L) -> msgs::ChannelReestablish where L::Target: Logger {
@@ -4375,8 +4443,7 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
43754443
// Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been
43764444
// called.
43774445

4378-
writer.write_all(&[SERIALIZATION_VERSION; 1])?;
4379-
writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
4446+
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
43804447

43814448
self.user_id.write(writer)?;
43824449
self.config.write(writer)?;
@@ -4565,6 +4632,9 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
45654632
self.commitment_secrets.write(writer)?;
45664633

45674634
self.channel_update_status.write(writer)?;
4635+
4636+
write_tlv_fields!(writer, {}, {(0, self.announcement_sigs)});
4637+
45684638
Ok(())
45694639
}
45704640
}
@@ -4573,11 +4643,7 @@ const MAX_ALLOC_SIZE: usize = 64*1024;
45734643
impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
45744644
where K::Target: KeysInterface<Signer = Signer> {
45754645
fn read<R : ::std::io::Read>(reader: &mut R, keys_source: &'a K) -> Result<Self, DecodeError> {
4576-
let _ver: u8 = Readable::read(reader)?;
4577-
let min_ver: u8 = Readable::read(reader)?;
4578-
if min_ver > SERIALIZATION_VERSION {
4579-
return Err(DecodeError::UnknownVersion);
4580-
}
4646+
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
45814647

45824648
let user_id = Readable::read(reader)?;
45834649
let config: ChannelConfig = Readable::read(reader)?;
@@ -4739,6 +4805,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
47394805

47404806
let channel_update_status = Readable::read(reader)?;
47414807

4808+
let mut announcement_sigs = None;
4809+
read_tlv_fields!(reader, {}, {(0, announcement_sigs)});
4810+
47424811
let mut secp_ctx = Secp256k1::new();
47434812
secp_ctx.seeded_randomize(&keys_source.get_secure_random_bytes());
47444813

@@ -4815,6 +4884,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
48154884

48164885
channel_update_status,
48174886

4887+
announcement_sigs,
4888+
48184889
#[cfg(any(test, feature = "fuzztarget"))]
48194890
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
48204891
#[cfg(any(test, feature = "fuzztarget"))]

0 commit comments

Comments
 (0)