near / bounties

Specs for technical and non-technical work that earns NEAR tokens
https://devgovgigs.near.social
72 stars 8 forks source link

Java Borsh implementation | Bounty $3000 in NEAR #25

Closed ilblackdragon closed 3 years ago

ilblackdragon commented 4 years ago

Description

A Java library that allows to generically serialize and deserialize Borsh

Context

Borsh is binary serializer that NEAR uses. Java developers may want to use it to interact with NEAR. Borsh has a simple specification outlined at https://borsh.io

Also Rust and JS implementations can be found here: https://github.com/near/borsh

Ideally Java implementation should follow interface similar to Rust, where an existing class can be just serialized / deserialized without any extra code.

Acceptance Criteria

Bounty

$3000 in NEAR

artob commented 4 years ago

As discussed on a call with @potatodepaulo just now, I'm working on this bounty, expecting to deliver by end of next week.

artob commented 4 years ago

My in-the-works project is now public at github.com/artob/borshj. It's almost finished, I will wrap it up in the next days. Will have a call with @potatodepaulo about it shortly.

behaviary commented 4 years ago

@ailisp will review this code. @artob please let him know when you feel it's ready for a review.

ailisp commented 4 years ago

Looks it's overall finished and in good shipped. I reviewed existing code and here is something i found:

}


And test Rect can also be serialized and deserialized                                                          
artob commented 4 years ago

@ailisp Thanks for the (slightly premature, but appreciated!) review :) I will address your comments and push a new version for review in the next day or two.

Do you have any thoughts regarding what we should do for fuzz testing here? That is one of the listed acceptance criteria, but it wasn't obvious to me how to proceed on that, since decoding random bytes (such as produced by fuzzing) would need a schema to make sense of them.

MaksymZavershynskyi commented 4 years ago

You could use Java reflection to generate some random hierarchies of classes, then serialize them, deserialize the result and compare that it is the same as before serialization.

artob commented 3 years ago

@ailisp @nearmax All right, I've pushed a new version that I believe is ready for your substantive review and does address all previous comments as follows:

consider code reuse between BorshBuffer<>BorshReader BorshWriter<>BorshBuffer

I've refactored the implementation, moving common code into the new BorshInput and BorshOutput interfaces.

This way, the implementations of the user-facing BorshBuffer, BorshReader, and BorshWriter classes are focused only on their respective glue points (to NIO buffers and I/O streams, respectively).

And the easiest-to-use interaction points remain the Borsh.serialize() and Borsh.deserialize() static methods.

some TODO, like serialize array

I've implemented array serialization and deserialization now. The only TODO comments left in the code base now are to note where there might be optimization opportunities (no change in functionality) to pursue going forward.

reader and writer test not completed

I've added elementary BorshReader tests and BorshWriter tests.

That's probably sufficient, these being standard Java interfaces and what with the implementation of these classes being now pretty trivial, since all serialization code is shared with BorshBuffer and extensively exercised in the BorshBuffer tests.

consider add a recursive implements Borsh test cases, e.g.:

Thanks, I've added exactly this test case. And that all works fine.

Overall, we're now at more than functional parity with the Borsh implementation for TypeScript, so I believe the only substantial thing left to do is the fuzz testing (I'm working on that along the lines of @nearmax's suggest). Please do provide feedback if that's not the case.

artob commented 3 years ago

@ailisp @nearmax I've now implemented fuzz testing as well, based on @nearmax's suggestion. Using Java reflection plus cglib, we generate a random hierarchy of recursive Java classes, and roundtrip (using Borsh.serialize() followed by Borsh.deserialize()) instances thereof to find any edge cases. Looking good at high levels of iterations and deep nesting.

MaksymZavershynskyi commented 3 years ago

@ailisp Could you please take a look?

ailisp commented 3 years ago

@artob @nearmax I took a look, all comments are addressed and fuzzy test is done. The repo satisfies all of acceptance criteria and I think it's a beautiful implementation that can be a reference for borsh in other programming languages :+1:

Some additional improvements:

Sorry i was wrong on java enum, it still deserves a test.

artob commented 3 years ago

Thanks, @ailisp, I appreciate the review and the kind words. I'll add the additional improvements you mentioned as well :+1:

artob commented 3 years ago

We've moved the BorshJ repository to near/borshj and I've ticketed @ailisp's follow-up comments at https://github.com/near/borshj/issues/1.

@potatodepaulo Since this bounty is completed and has been paid out, you could go ahead and close this?