Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add ability to broadcast our own node_announcement - #435

Merged
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce
Mar 9, 2020
Merged

Add ability to broadcast our own node_announcement#435
TheBlueMatt merged 5 commits into
lightningdevkit:masterfrom
TheBlueMatt:2020-01-node_announce

Conversation

@TheBlueMatt

Copy link
Copy Markdown
Collaborator

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).

Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.

@TheBlueMatt

TheBlueMatt commented Jan 3, 2020

Copy link
Copy Markdown
CollaboratorAuthor

Based on #434 cause Im too lazy to properly rebase it.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch 5 times, most recently from c7f02e3 to c372439CompareJanuary 8, 2020 01:08

@ariardariard left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to fix few comments otherwise looks good.

Comment threadlightning/src/ln/msgs.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastNodeAnnouncement {
msg: msgs::NodeAnnouncement {
signature: self.secp_ctx.sign(&msghash, &self.our_network_key),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we may wanna provide an interface for external signers later

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right. For now the external signing support hasn't even attempted to think about moving the node_id private key out, given its used in a ton of places. Eventually it'll need to be (well, probably after splitting it up more), but for now it is what it is.

Comment threadlightning/src/ln/msgs.rs Outdated
}
}

/// A "set" of addresses which enforces that there can be only up to one of each net address type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how does this actually enforce that the underlying NetAddress objects behave are what's expected?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Because the public API only allows you to add one address per type (replacing the previous one if there is one already).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see the set_address methods now. Also, hadn't realized NetAddress wasn't a standard library.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@arik-so FWIW, there is SocketAddrV4 and SocketAddrV6.

https://doc.rust-lang.org/std/net/index.html

Comment threadlightning/src/ln/peer_handler.rs
}
}
},
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

if Rust had a way of distributing match arms across multiple files, this would be the place

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I'm not sure what you mean here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I was referring to the fact that we're adding yet another match arm to a match that's hundreds of lines long.


features: NodeFeatures,
last_update: u32,
last_update: Option<u32>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the rationale for moving last_update into an Option as part of this diff? Also, there should be a comment somewhere saying it's a timestamp.

And also, this will break 18 years from now 😛

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

As otherwise we'll reject a 0 value (as we only accept anything newer than the previous value). Also note that it is not a timestamp, the spec only recommends that you use a timestamp. See-also #493. I added a comment noting that None implies we've not heard any updates yet.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 12, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 13, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 15, 2020
@TheBlueMattTheBlueMatt added this to the 0.0.10 milestone Feb 17, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 19, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 20, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 21, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 23, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 24, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 25, 2020
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Addressed Jeff's feedback and added a commit which resolves #493.

@TheBlueMattTheBlueMatt linked an issue Feb 27, 2020 that may be closed by this pull request
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 28, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Feb 29, 2020
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 1, 2020

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice, very key feature!

Comment threadlightning/src/ln/peer_handler.rs Outdated
let encoded_msg = encode_msg!(msg);

for (ref descriptor, ref mut peer) in peers.peers.iter_mut() {
if !peer.channel_encryptor.is_ready_for_encryption() || peer.their_features.is_none() ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would a Peer not have their_features set?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Before we've received their Init message (which will be the first message we receive, or we'll disconnect them), it should be None.

Comment threadlightning/src/util/events.rs
Comment threadlightning/src/ln/channelmanager.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated

let announcement = msgs::UnsignedNodeAnnouncement {
features: NodeFeatures::supported(),
timestamp: self.last_node_announcement_serial.fetch_add(1, Ordering::AcqRel) as u32,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

reasoning for AcqRel?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

AcqRel is a good default - it ensures we always have the latest value here, without acting as a lock (as SeqCst does). If we're not relying on any other data to be consistent, but want consistency ourselves, AcqRel it is. Note that, on x86, AcqRel compiles down to nothing, whereas SeqCst is relatively expensive.

node_id: self.get_our_node_id(),
rgb, alias,
addresses: addresses.into_vec(),
excess_address_data: Vec::new(),

@valentinewallacevalentinewallaceMar 4, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since this is our node announcement, we'll never have any excess address data, right? this is just for remote peer NodeAnnouncements that may randomly have excess address data? is this a common problem...?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

That is correct. And, indeed, it is not a common thing. We have to have it as otherwise the signatures of things we relay will fail, but, in general, we anticipate almost never having anything in there, or if we do, a very small thing.

Comment on lines +2760 to +2790
loop {
// Just in case we end up in a race, we loop until we either successfully update
// last_node_announcement_serial or decide we don't need to.
let old_serial = self.last_node_announcement_serial.load(Ordering::Acquire);
if old_serial < header.time as usize {
if self.last_node_announcement_serial.compare_exchange(old_serial, header.time as usize, Ordering::AcqRel, Ordering::Relaxed).is_ok() {
break;
}
} else { break; }
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Confused about this loop -- we don't broadcast a NodeAnnouncement in this function, so what's the point of updating last_node_announcement_serial?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

The compare_exchange updates it - the goal here is to update the value iff the block timestamp is >= the current latest value. I updated the comment to note that. Rust does have a method for this, but sadly its nightly-only (and it should compile down to something similar, just maybe with more optimal/effecient Orderings.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, so the purpose is to have a "fresh" timestamp for the next time we do broadcast a node announcement

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b727baf to 4334755CompareMarch 5, 2020 03:32
@codecov

codecovBot commented Mar 5, 2020

Copy link
Copy Markdown

Codecov Report

Merging #435 into master will increase coverage by 0.35%.
The diff coverage is 69.23%.

Impacted file tree graph

@@ Coverage Diff @@## master #435 +/- ##
==========================================
+ Coverage 89.75% 90.11% +0.35% 
==========================================
Files 34 34 Lines 18991 19054 +63 ==========================================
+ Hits 17046 17170 +124 + Misses 1945 1884 -61 
Impacted FilesCoverage Δ
lightning/src/ln/peer_handler.rs48.70% <0.00%> (-1.39%)⬇️
lightning/src/ln/channelmanager.rs85.78% <0.00%> (+0.11%)⬆️
lightning/src/ln/functional_tests.rs96.42% <0.00%> (+0.12%)⬆️
lightning/src/util/ser_macros.rs97.27% <0.00%> (+0.68%)⬆️
lightning/src/ln/onion_utils.rs94.97% <0.00%> (+1.09%)⬆️
lightning/src/ln/router.rs91.08% <0.00%> (+2.28%)⬆️
lightning/src/ln/msgs.rs88.10% <0.00%> (+4.53%)⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d850e12...78c48f7. Read the comment docs.

TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 4334755 to b8a4c45CompareMarch 5, 2020 19:07
Comment threadlightning/src/ln/channelmanager.rs Outdated
excess_address_data: Vec::new(),
excess_data: Vec::new(),
};
let msghash = hash_to_message!(&Sha256dHash::hash(&announcement.encode()[..])[..]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just to be sure -- spec says the signature should be over the double hash, and this seems to be a single hash?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, bitcoin_hashes types are confusing. That tiny little d that easy to miss means double :).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, it is easy to miss.. 😅

per_peer_state.insert(peer_pubkey, Mutex::new(peer_state));
}

let last_node_announcement_serial: u32 = Readable::read(reader)?;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, in theory could this cause a user migrating error?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yea, we currently do no version checking for serialized types and break things all the time. We'll need to fix this come 0.1, but for now, no reason to slow down to build compatibility with 0.0.X.

Comment on lines +399 to +416
let a_events = nodes[a].node.get_and_clear_pending_msg_events();
assert_eq!(a_events.len(), 1);
let a_node_announcement = match a_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new());
let b_events = nodes[b].node.get_and_clear_pending_msg_events();
assert_eq!(b_events.len(), 1);
let b_node_announcement = match b_events[0] {
MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => {
(*msg).clone()
},
_ => panic!("Unexpected event"),
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment threadlightning/src/ln/channel.rs Outdated
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from b8a4c45 to 295bde3CompareMarch 5, 2020 21:17

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good modulo some minor comments mostly around magic numbers. I had to dig through the BOLTs to discern their meaning. Using constants would prevent posterity from needing to do the same thing.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It wasn't readily apparent to me that that the + 1 was for the address type. Could you make a constant for this using ::std::mem::size_of::<u8>?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its explicit in the docs for MAX_LEN - there is a 1-byte type. I don't think mem::size_of makes that any clearer.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Right, but the 1 is explicit in the documentation for the len() method as well as the MAX_LEN docs, if we want to change the definition of that stuff we can, but any future users will see pretty clearly whats up. Using u16::MAX is fine, and I agreed it wasn't clear, so a comment was added indicating that its a message length.

Comment threadlightning/src/ln/msgs.rs
Comment threadlightning/src/ln/channelmanager.rs Outdated
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
const STATIC_ASSERT: u32 = Self::HALF_MESSAGE_IS_ADDRS - 500; // This will fail to compile if we use half of the message with 500 addresses

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use a constant for 500 since it is used in two places.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Its also written in the docs, so a comment confusingly indicates you may be able to change it freely (which you are not). The new comment I added to describe this const check a bit more explicitly calls it out as our public contract, is that fine?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm assuming you meant "a constant confusingly indicates you may be able to change it freely".

Isn't the point of a constant that it can't change? Saying that if a number is used in documentation we can't make it a constant seems rather silly. Just reference the constant in the documentation then. The actual value 500 seems rather unimportant in this case.

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

I tend to presume that if I see a constant I can change it, and the code will change appropriately. Same goes for a user who sees a constant referenced in documentation - it may change in a future version and code should handle it. That isn't the case here, so having the number appear three times across ten lines of code where one is in documentation seems like a better approach to me.

@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 295bde3 to bd69f0dCompareMarch 5, 2020 23:01
Unlike channel_update messages, node_announcement messages have no
requirement that the timestamp is greater than 0.
lnd has been blatantly ignoring this line in the spec forever, so
its somewhat of a lost cause trying to enforce it.
TheBlueMatt added a commit to TheBlueMatt/rust-lightning that referenced this pull request Mar 5, 2020
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from bd69f0d to 48ee31fCompareMarch 5, 2020 23:43
@TheBlueMatt

Copy link
Copy Markdown
CollaboratorAuthor

Go travis fuzz checks, which caught a bug that would have been introduced here where we deduped addresses we read ending up writing only a subset of what we read which fails the strictness checks we need to apply on announcement messages.

Comment threadlightning/src/ln/channelmanager.rs Outdated
Comment threadlightning/src/ln/channelmanager.rs Outdated
}

#[allow(dead_code)]
const HALF_MESSAGE_IS_ADDRS: u32 = 64*1024 / (msgs::NetAddress::MAX_LEN as u32 + 1) / 2;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I only suggested to use mem::size_of when defining a constant. Fine to use a literal as well.

The point of defining a constant for 1 is to make its meaning explicit. Same goes for ::std::u16::MAX.

@jkczyzjkczyz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not gonna hold this up with the last few comments, but I just want to state there's a good rationale for them. :) They may seem trivial, but I make sure to fully understand code that I review. And if there is something that is not obvious, I assume it may not be obvious to others reading the code. Thus, I try to make suggestions that will save other readers time.

This is a somewhat-obvious oversight in the capabilities of
rust-lightning, though not a particularly interesting one until we
start relying on node_features (eg for variable-length-onions and
Base AMP).
Sadly its not fully automated as we don't really want to store the
list of available addresses from the user. However, with a simple
call to ChannelManager::broadcast_node_announcement and a sensible
peer_handler, the announcement is made.
Fixes issue lightningdevkit#493 and should resolve some issues where other nodes
(incorrectly) reject channel_update/node_announcement messages
which have a serial number that is not a relatively recent
timestamp.
@TheBlueMatt
TheBlueMattforce-pushed the 2020-01-node_announce branch from 48ee31f to 78c48f7CompareMarch 6, 2020 02:00

@valentinewallacevalentinewallace left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, nice progress on 0.0.11! 🏄‍♀️

Comment on lines +1344 to +1345
// Messages of up to 64KB should never end up more than half full with addresses, as that would
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hm, this isn't an actual spec rule, though, is it (mod the issue that this PR addresses)? >500 does seem extreme and I don't have an issue with enforcing it, just not sure the exact purpose of enforcing it...

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

IIRC (and if it doesn't it should) if we went to serialize it we'd generate something >64KB, panicing trying to send a message that overflows the max message size.

Comment on lines +1371 to +1373
if addresses.len() > 500 {
panic!("More than half the message size was taken up by public addresses!");
}

@valentinewallacevalentinewallaceMar 6, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good target for whomever addresses #529

@TheBlueMatt
TheBlueMatt merged commit 83c9eb4 into lightningdevkit:masterMar 9, 2020
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Swap announcement/update serials for block timestamp.

5 participants

@TheBlueMatt@arik-so@jkczyz@valentinewallace@ariard