Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAUZED] feat: (de-)serialize whole packet #4

Closed
wants to merge 3 commits into from

Conversation

michielbdejong
Copy link
Contributor

No description provided.

@michielbdejong michielbdejong changed the base branch from master to da-deserialize-packet August 28, 2017 12:15
@michielbdejong
Copy link
Contributor Author

Rebased on #5. This PR questions why you would ever want to serialize, or deserialize, only the 'data' part of a clp packet, and simplifies it all by collapsing the many serialize* functions into one serialize function with a switch statement, and the same for deserialize.

To indicate what type of clp packet you are serializing, just set the .type field to one of the constants exposed by the module. The single argument for serialize is the same object as what deserialize return, and the simplification this offers can be seen nicely in the unit tests.

Copy link

@dappelt dappelt left a comment

Choose a reason for hiding this comment

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

Removing the serialize* functions breaks a lot of existing code. I prefer to have an expressive function name than passing in the packet type as an argument. Also, ilp-packet names the functions in the scheme serialize_PacketType_. For a consistent developer experience, we should keep the serialize_PacketType_ functions.

@dappelt
Copy link

dappelt commented Aug 28, 2017

This PR questions why you would ever want to serialize, or deserialize, only the 'data' part of a clp packet, and simplifies it all by collapsing the many serialize* functions into one serialize function with a switch statement, and the same for deserialize.

serializing and deserializing are different in this aspect. When a peer is sending a packet we typically don't know its type, so a deserialize function that takes any packet and returns the type and packet data is handy. On the other hand, when you serialize a packet you need to know which type of packet you want to create. Therefore, having several serialize functions is nice.

Anyway, if you want to add a serialize function that takes the packet type as an argument, add this function as an alias (i.e. without removing the existing serialize* functions).

index.js Outdated
} break

case TYPE_PREPARE: {
const transferIdBuffer = Buffer.from(obj.data.transferId.replace(/\-/g, ''), 'hex')
Copy link

Choose a reason for hiding this comment

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

That's a zombie bug. I removed the backslash in the previous commit and now its back ;-) (that backslash is unnecessary)

index.js Outdated
packet: deserializeMessage(buffer) }
default:
throw new Error('Packet has invalid type')
function deserialize (buffer) {
Copy link

Choose a reason for hiding this comment

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

I am not a fan of collapsing everything in one method. It reduces readability.

Also, you removed typeString.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I'll reinstate the separate methods.

About the typeString, what is it needed for? It just duplicates the type constant, right?
Adding that as a field just breaks it away from the asn.1 format, so that's quite ugly. What is the use case, just to make the logs more readable? Would it be ok if I just add a static function typeToString to the module exports, that converts from e.g. ClpPacket.TYPE_ACK to the string 'ack'?

Copy link

Choose a reason for hiding this comment

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

Yes, typeString is handy for logging. Replacing it with a function is fine.

Copy link

Choose a reason for hiding this comment

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

However, the current return type (i.e. containing a typeString) is consistent with ilp-packet. Although I agree that a static function would be cleaner, we might want to keep typeString for consistency. (or change ilp-packet also to a static function if that does not break too many dependencies.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok. i'll open an issue on ilp-packet because i do like it a lot better as a separate function. This way, the object returned by deserialize is the same as the object you need to give to serialize. Adding typeString inside the return object would mean obj === deserialize(serialize(obj)) would no longer be true.

@michielbdejong
Copy link
Contributor Author

@dappelt all comments addressed, and rebased on master.

Copy link

@dappelt dappelt left a comment

Choose a reason for hiding this comment

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

The serialize* functions are still missing.

@michielbdejong
Copy link
Contributor Author

sorry, hadn't seen your remark about restoring those functions. done now. also added more tests.

index.js Outdated
deserializeAck (buffer) {
const obj = deserialize(buffer)
return {
requestId: obj.requestId,
Copy link

@dappelt dappelt Aug 29, 2017

Choose a reason for hiding this comment

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

There is an inconsistency between deserialize and the deserialize_Type_() functions. The former returns requestId as a field in the envelope, the latter returns requestId as a field in data.

So if you compare the objects returned from clp.deserialize(packet).data to clp.deserializePrepare(packet) the objects will not be the same because of requestId.

Copy link

Choose a reason for hiding this comment

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

How about putting requestId always into the data field?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, clp.deserialize follows the OER format, and clp.deserializePrepare etc follow the slightly different format which Ben introduced. The reason these legacy functions are still there is that they are used in the payment channel framework. I implemented them because you said 'Removing the serialize* functions breaks a lot of existing code' in your previous review. Changing them would break that existing code just as much as removing them.

Copy link

Choose a reason for hiding this comment

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

Michiel and I settled over slack to remove the type specific deserialization functions (clp.deserializePrepare(..) etc.).

@michielbdejong michielbdejong dismissed dappelt’s stale review August 29, 2017 14:25

removed deserialize* as discussed. kept that in a separate commit in case we ever want to revert it. please re-review.

@michielbdejong michielbdejong changed the base branch from da-deserialize-packet to master August 29, 2017 14:26
case TYPE_ACK:
case TYPE_RESPONSE:
case TYPE_MESSAGE:
data = readProtocolData(reader) // see https://github.com/interledger/rfcs/issues/284
Copy link

Choose a reason for hiding this comment

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

That is a breaking change. Can we make this for now non-breaking by changing this line to data = {protocolData: readProtocolData(reader).

Also see this related PR to make the specs match the implementation: interledger/rfcs#285

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A bug fix is by definition breaking the behavior for people who relied on that bug being present :)

Copy link

Choose a reason for hiding this comment

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

This wasn't a bug in the first place, but intentional to avoid the problems outlined in interledger/rfcs#284.

Lets merge interledger/rfcs#285 an be done with it.

case TYPE_ACK:
case TYPE_RESPONSE:
case TYPE_MESSAGE:
data = readProtocolData(reader) // see https://github.com/interledger/rfcs/issues/284
Copy link

Choose a reason for hiding this comment

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

This wasn't a bug in the first place, but intentional to avoid the problems outlined in interledger/rfcs#284.

Lets merge interledger/rfcs#285 an be done with it.

@michielbdejong
Copy link
Contributor Author

clp-packet currently has "bugs" (deviations from the spec) which correspond to open PRs on the RFCs repo. (e.g. https://github.com/interledger/rfcs/pull/285/files)

I tried to fix those, but some of Dennis's code relies on these bugs, and since the behavior may become the new correct behavior, it's a waste of work to merge these fixes now as breaking changes, and then revert them next week when the spec changes.

@dappelt and I have both put multiple hours into trying to get to a single clp-packet code base that both he and I are happy with, and we failed.

But luckily we agreed there will be a spec freeze starting 18 september, so parking this PR until then, hopefully it will be easier once we at least know what the correct behavior is on the wire.

@michielbdejong michielbdejong changed the title feat: (de-)serialize whole packet [PAUZED] feat: (de-)serialize whole packet Aug 29, 2017
@dappelt
Copy link

dappelt commented Aug 29, 2017

It's the spec that has a bug not the code ;-) In fact, we both agree that the spec has a bug: interledger/rfcs#284

I think we should fix the spec, change the single line that is affected by the spec change and merge your PR.

@michielbdejong
Copy link
Contributor Author

It's about the speed at which spec versions succeed each other. Yesterday, I wrote down that day's version of CLP in https://github.com/interledger/interledger/wiki/Interledger-over-CLP#clp, and I pushed this branch with a working implementation of CLP as defined in that wiki page.

I don't care about any other spec version than the version I'm using for the testnet. I had hoped that it would remain "the latest version" for at least a week or so, but that didn't happen. So now I guess the master branch of this repo will track the spec changes as they happen, and I'll just keep using my forked branch for the testnet.

It's a win-win for everybody: you can propose, discuss, and implement the changes you want to, and I can work on the testnet without being distracted by daily or weekly spec changes. That's why I pauzed this PR.

@michielbdejong
Copy link
Contributor Author

I implemented #8 in 5a45886

@michielbdejong
Copy link
Contributor Author

Not sure what happened, but this PR was for 'collapsing the many serialize* functions into one serialize function with a switch statement, and the same for deserialize' and these methods exist in master now, so this PR can be closed. :)

@michielbdejong
Copy link
Contributor Author

Ah right, looks like this PR's commits were mostly included in #11. 👍

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.

None yet

2 participants