Skip to content

Conversation

positiveblue
Copy link
Contributor

This PR includes the client changes for including node id constrains to pool orders. The users will be able to add a list of allowed/not allowed node ids for their order.

Thinks to take into account:

  • Every order has its own constrains. I may not want to match with someone in order X but not filter him out in order Y.
  • The filters are included during the order creation. This is important for sidecars because the provider may need to get the information from the recipient before creating the sidecar.

Copy link
Contributor

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Very nice and clean PR!
Only a few minor comments about the TLV encoding/decoding, everything else looks pretty good 🎉

// List of nodes that will be allowed to match with our order.
repeated bytes allowed_node_ids = 14;

// List of nodes that won't be allowed to match with our order.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: add a comment to both that the lists are mutually exclusive.

@@ -116,6 +116,18 @@ var sharedFlags = []cli.Flag{
channelTypePeerDependent,
channelTypeScriptEnforced),
},
cli.StringSliceFlag{
Name: "allowed_node_ids",
Copy link
Contributor

Choose a reason for hiding this comment

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

I assume this is specified multiple times to add multiple IDs? Perhaps the flag name should be singular then and the description should say "can be specified multiple times".

if len(details.AllowedNodeIds) > 0 &&
len(details.NotAllowedNodeIds) > 0 {

return nil, errors.New("my story")
Copy link
Contributor

Choose a reason for hiding this comment

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

😂

@@ -689,6 +698,29 @@ func deserializeOrderTlvData(r io.Reader, o order.Order) error {
o.Details().ChannelType = order.ChannelType(channelType)
}

if allowedNodeIDsBytes, ok := parsedTypes[allowedNodeIDsType]; ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't really correct. You only get the allowedNodeIDsBytes != nil when the TLV library considers this to be an "unknown record type". So instead you should add a primitive record to the top that just expects a byte slice. Then here you can just check t, ok := parsedTypes[allowedNodeIDSType]; ok && t == nil and expect that byte slice to be filled with the data you want.

if allowedNodeIDsBytes, ok := parsedTypes[allowedNodeIDsType]; ok {
numberOfItems := len(allowedNodeIDsBytes) / 33
o.Details().AllowedNodeIDs = make([][33]byte, numberOfItems)
if err := binary.Read(
Copy link
Contributor

Choose a reason for hiding this comment

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

This falls back to some reflection magic. Since we know exactly that we're serializing and de-serializing a slice of arrays, should we add two helper functions that then do the explicit 33 byte calculation? Then we can just use copy() and don't need binary.Read() or a buffer for the reverse.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean flattering the [][33]byte to a []byte and then use the default tlv types serialize/deserialize? then add a function to transform from []byte to [][33]byte?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, exactly. Feels more robust and performant than relying on some reflection code of binary.Read().

// It is not possible for a oder to have AllowedNodeIDs and
// NotAllowedNodeIDs at the same time but we want to test
// serialization/deserialization here.
o.Details().AllowedNodeIDs = [][33]byte{{1, 2, 3}}
Copy link
Contributor

Choose a reason for hiding this comment

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

we should add at least two IDs to make sure multiple entries can be stored and retrieved correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh I run it manually to actually test the maximum number, 1000 is ok, 10000 is to much for tlv encoding. I will add few more for the automatic test ✔️

@positiveblue positiveblue force-pushed the nodefilters branch 6 times, most recently from 40651e1 to 986929a Compare March 31, 2022 05:53
@positiveblue positiveblue requested a review from guggero March 31, 2022 06:08
Copy link
Contributor

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Very nice, only nits remaining. Going to do a full test run while reviewing the subasta PR.

Name: "allowed_node_id",
Usage: "the list of nodes this order is able to match with; " +
"if empty, the order will be able to match with any " +
"node unless not_allowed_node_id is set. Cann be " +
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo in "Cann"

},
cli.StringSliceFlag{
Name: "not_allowed_node_id",
Usage: "the list of nodes this order is not able to match " +
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: s/not able to match with/not allowed to match with? "not able" implies a problem, but this is just a user preference.

},
cli.StringSliceFlag{
Name: "not_allowed_node_id",
Usage: "the list of nodes this order is not able to match " +
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: s/not able to match with/not allowed to match with? "not able" implies a problem, but this is just a user preference.

@@ -340,6 +340,14 @@ type Kit struct {
// ChannelType denotes the channel type that must be used for the
// resulting matched channels.
ChannelType ChannelType

// AllowedNodeIDs is the list of node ids this order is allowed to
// macth with.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo in "match", here and comment below.

@@ -340,6 +340,14 @@ type Kit struct {
// ChannelType denotes the channel type that must be used for the
// resulting matched channels.
ChannelType ChannelType

// AllowedNodeIDs is the list of node ids this order is allowed to
// macth with.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: type in "match".

flatten := make([]byte, len(pubKeys)*33)

for i, key := range pubKeys {
for j, v := range key {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: could also use copy() here to avoid a nested loop.


for i := 0; i < numOfPubKeys; i++ {
var pubKey [33]byte
for j := 0; j < 33; j++ {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, can just use copy with the correct slice indices.


for i := 0; i < numOfPubKeys; i++ {
var pubKey [33]byte
for j := 0; j < 33; j++ {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, can just use copy with the correct slice indices.

order/manager.go Outdated
return true
}

// If we get here is because both lists were empty
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: missing full stop.

order/manager.go Outdated
return true
}

// If we get here is because both lists were empty
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: missing full stop.

@guggero
Copy link
Contributor

guggero commented Apr 4, 2022

Needs a rebase as well.

@positiveblue positiveblue force-pushed the nodefilters branch 2 times, most recently from 0aa913a to 86427e0 Compare April 6, 2022 00:26
@positiveblue positiveblue requested a review from bhandras April 6, 2022 00:42
Copy link
Member

@bhandras bhandras left a comment

Choose a reason for hiding this comment

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

Great PR @positiveblue just a few nits, otherwise LGTM 🎉

"Can be specified multiple times",
},
cli.StringSliceFlag{
Name: "not_allowed_node_id",
Copy link
Member

Choose a reason for hiding this comment

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

nit: maybe just for the cli we could consider renaming this to prohibited_node_id. Potentially even for the protocol if you think it's better and it's still possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure about this one. I could change it only in the CLI, but it could leak from some rpc_server errors and potentially confuse the user. For example, parsing the order could return invalid not_allowed_node_id.

Is it because for native speakers prohibited_node_id sounds better than not_allowed_node_id? If so I can change it everywhere, just not sure if it is just a matter of taste.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I'm not sure either given I'm not native but just thought it's simpler as "prohibited" is just one word. Regardless I'm fine with the current choice too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Prohibited sounds good to me. Or just disallowed. "not allowed" does sound a bit bumpy.

Copy link
Contributor

Choose a reason for hiding this comment

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

But this probably also requires quite a big refactor/renaming so we can also just leave it the way it is.

for _, hexNodeID := range hexNodeIDs {
nodeID, err := hex.DecodeString(hexNodeID)
if err != nil {
return nil, fmt.Errorf("invalid node ID %v: %v", nodeID,
Copy link
Member

Choose a reason for hiding this comment

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

nit: I think nodeID might be empty here since DecodeString failed so it's better to print hexNodeID.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Much better 👍

[][]byte, len(o.Details().AllowedNodeIDs),
)
for idx, nodeID := range o.Details().AllowedNodeIDs {
details.AllowedNodeIds[idx] = nodeID[:]
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if this is safe? Since nodeID is restricted to the scope of the for loop.

Copy link
Contributor Author

@positiveblue positiveblue Apr 7, 2022

Choose a reason for hiding this comment

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

Good intuition. In Go, the runtime is the one that decides what goes in the stack/heap (the specification does not define it). So, even for pointers, the obj would survive the scope.

Copy link
Member

Choose a reason for hiding this comment

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

I actually ran a little experiment, because I wasn't quite sure myself. PTAL: https://go.dev/play/p/geeXf0C5E6m

Copy link
Contributor Author

@positiveblue positiveblue Apr 7, 2022

Choose a reason for hiding this comment

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

ohhh, you are right. The var will out live the loop but all the elements in the slice of []byte will be equal to the last one!

fix: https://go.dev/play/p/hFON1QWCoOY

🙏 Thank you for catching this @bhandras

Copy link
Member

Choose a reason for hiding this comment

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

It's tricky and I think the compiler/linter should be more vocal about this as it's easy to miss.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh wow, good catch! I wouldn't have caught that one 😮

@positiveblue positiveblue force-pushed the nodefilters branch 2 times, most recently from aba4666 to 53b437d Compare April 7, 2022 15:37
Copy link
Contributor

@guggero guggero left a comment

Choose a reason for hiding this comment

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

Code looks good to me now!

Though I think we should wait with merging this until we have the server version deployed! Otherwise users will still get matched according to the old rules and be unsure why. Perhaps we should even go ahead and add a new order version for this?

Name: "allowed_node_id",
Usage: "the list of nodes this order is able to match with; " +
"if empty, the order will be able to match with any " +
"node unless not_allowed_node_id is set. Cann be " +
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: typo in "Cann"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did you already have the tab for the review open? It looks like it was already fixed

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh yeah. Old comment, sorry. Please ignore 😅

"Can be specified multiple times",
},
cli.StringSliceFlag{
Name: "not_allowed_node_id",
Copy link
Contributor

Choose a reason for hiding this comment

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

Prohibited sounds good to me. Or just disallowed. "not allowed" does sound a bit bumpy.

"Can be specified multiple times",
},
cli.StringSliceFlag{
Name: "not_allowed_node_id",
Copy link
Contributor

Choose a reason for hiding this comment

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

But this probably also requires quite a big refactor/renaming so we can also just leave it the way it is.

@lightninglabs-deploy
Copy link
Collaborator

@positiveblue, remember to re-request review from reviewers when ready

@positiveblue positiveblue merged commit 6601e0e into master Apr 26, 2022
@guggero guggero deleted the nodefilters branch May 5, 2022 15:25
positiveblue pushed a commit to positiveblue/pool that referenced this pull request Oct 11, 2022
…_fix

subastadb: make etcd prefix queries paginated to avoid timeouts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants