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

sdk: Limited Borsh 0.9 support (Pubkey and helpers) #32511

Merged
merged 9 commits into from
Aug 2, 2023

Conversation

joncinque
Copy link
Contributor

@joncinque joncinque commented Jul 17, 2023

Problem

The upgrade to Solana 1.16 crates has been very painful for a number of teams due to the incompatibility between Borsh 0.9 and 0.10, which should have constituted a major version upgrade for the Solana SDK crates. A lot of these are due to the borsh 0.9 traits not being implemented on the SDK types, not counting the issues like #31960

Summary of Changes

To alleviate one class of issues, also implement the borsh 0.9 traits on Pubkey.

Note that it still won't be possible to build the metaplex crates because they use the solana_program::borsh::get_packed_len helper, which targets borsh 0.10 in the solana crates. The solution here is to version the solana helpers and deprecate the general solana_program::borsh file. This way, it's impossible to break people when we add support for a new version of borsh.

This will also be backported to 1.16.

These manual implementations were generated by running cargo expand on borsh 0.9, copy-pasting, and then adding the proper annotations everywhere to use borsh 0.9 versions.

Fixes #

@mvines
Copy link
Member

mvines commented Jul 17, 2023

Note that it still won't be possible to build the metaplex crates because they use the solana_program::borsh::get_packed_len helper, which targets borsh 0.10 in the solana crates.

To build metaplex, would a borsh 0.9 version of get_packed_len need to be reintroduced?

@t-nelson
Copy link
Contributor

t-nelson commented Jul 17, 2023

can we not derive() the fully qualified macro name instead of copypastaing the expanded version?

that is, something like...

#[derive(BorshSerialized, borsh0_9::BorshSerialize)]
struct Pubkey...

@joncinque
Copy link
Contributor Author

To build metaplex, would a borsh 0.9 version of get_packed_len need to be reintroduced?

Yes, but only if it's at solana_program::borsh::get_packed_len, which would revert the behavior. Unless there's a way to define a function twice with different trait params. So practically, I don't think so

can we not derive() the fully qualified macro name instead of copypastaing the expanded version?

No, the macro uses borsh:: under the hood, which gets interpreted to the newest version

@t-nelson
Copy link
Contributor

No, the macro uses borsh:: under the hood, which gets interpreted to the newest version

ugh. didn't realize that $crate isn't available in proc-macros 🤢

carry on

@codecov
Copy link

codecov bot commented Jul 18, 2023

Codecov Report

Merging #32511 (346d75d) into master (3dcb382) will decrease coverage by 0.1%.
The diff coverage is 74.6%.

@@            Coverage Diff            @@
##           master   #32511     +/-   ##
=========================================
- Coverage    82.0%    82.0%   -0.1%     
=========================================
  Files         785      785             
  Lines      211100   211073     -27     
=========================================
- Hits       173170   173106     -64     
- Misses      37930    37967     +37     

@mvines
Copy link
Member

mvines commented Jul 18, 2023

To build metaplex, would a borsh 0.9 version of get_packed_len need to be reintroduced?

Yes, but only if it's at solana_program::borsh::get_packed_len, which would revert the behavior. Unless there's a way to define a function twice with different trait params. So practically, I don't think so

Restore solana_program::borsh to be borsh 0.9, and add a solana_program::borsh0_10 module for borsh 0.10?

@joncinque
Copy link
Contributor Author

Restore solana_program::borsh to be borsh 0.9, and add a solana_program::borsh0_10 module for borsh 0.10?

We could, but then we break people who have upgraded 😅

@mvines
Copy link
Member

mvines commented Jul 18, 2023

Restore solana_program::borsh to be borsh 0.9, and add a solana_program::borsh0_10 module for borsh 0.10?

We could, but then we break people who have upgraded 😅

Yeah, ⚖️. That's ideally what we would have done from the start probably, but yeah probably too late for that now. Are you thinking of adding a solana_program::borsh0_9::get_packed_len then?

@joncinque
Copy link
Contributor Author

Are you thinking of adding a solana_program::borsh0_9::get_packed_len then?

I wasn't planning on it, since it wouldn't solve the initial metaplex build issue. But thinking on it more, it could be used if an upgraded program wants to do use the helpers on older types. I'll add it in

@joncinque joncinque changed the title sdk: Manually implement Borsh 0.9 traits on Pubkey sdk: Limited Borsh 0.9 support (Pubkey and helpers) Jul 25, 2023
@joncinque
Copy link
Contributor Author

Sorry for the holdup here, I added the borsh0_9.rs helpers. The file is exactly copy-pasted from borsh.rs, but with different imports. I omitted the tests because they will require manually implementing all of the Borsh traits on the test types, and that didn't seem worth the time. Let me know if you disagree!

@ilya-bobyr
Copy link
Contributor

ilya-bobyr commented Jul 25, 2023

No, the macro uses borsh:: under the hood, which gets interpreted to the newest version

ugh. didn't realize that $crate isn't available in proc-macros nauseated_face

There are solutions like this: https://docs.rs/proc-macro-crate/1.3.1/proc_macro_crate/
Not ideal.


My bad. borsh actually uses this crate.
It helps with renames, but it will still choose just one version of the crate.
The one that is the last in Cargo.toml.

@ilya-bobyr
Copy link
Contributor

can we not derive() the fully qualified macro name instead of copypastaing the expanded version?

No, the macro uses borsh:: under the hood, which gets interpreted to the newest version

There is a way to use borsh implementation in both cases, but it requires a proxy crate.
Here is an example: https://github.com/ilya-bobyr/borsh-multi-version/

To build metaplex, would a borsh 0.9 version of get_packed_len need to be reintroduced?

Yes, but only if it's at solana_program::borsh::get_packed_len, which would revert the behavior. Unless there's a way to define a function twice with different trait params. So practically, I don't think so

I do not think this is possible.
Exactly because it is possible to define both 0.9 and 0.10 versions of the BorshSchema for a type.
At which point, the get_packed_len call becomes ambiguous.

@joncinque
Copy link
Contributor Author

There is a way to use borsh implementation in both cases, but it requires a proxy crate.
Here is an example: https://github.com/ilya-bobyr/borsh-multi-version/

Very cool, thanks for showing how to do it!

Actually, while I have you here @ilya-bobyr ... I was thinking of moving the borsh dependency entirely out of the sdk, and do it through some sort of new crate like solana-borsh, probably through some new proxy traits defined in that crate. but I think that might just shift the problem elsewhere and not actually help. What do you think of that approach?

And what do you think of this PR? I'd like to land it soon to help adoption of 1.16

@ilya-bobyr ilya-bobyr self-requested a review July 26, 2023 20:49
@joncinque
Copy link
Contributor Author

@ilya-bobyr as discussed offline, I've also added borsh0_10.rs and re-export everything from that file in borsh.rs

ilya-bobyr
ilya-bobyr previously approved these changes Jul 29, 2023
sdk/program/src/borsh0_10.rs Outdated Show resolved Hide resolved
sdk/program/src/borsh0_9.rs Outdated Show resolved Hide resolved
sdk/program/src/pubkey.rs Show resolved Hide resolved
ilya-bobyr
ilya-bobyr previously approved these changes Aug 1, 2023
sdk/program/src/borsh0_9.rs Outdated Show resolved Hide resolved
sdk/program/src/borsh0_10.rs Outdated Show resolved Hide resolved
@joncinque joncinque merged commit 8c14886 into solana-labs:master Aug 2, 2023
15 checks passed
@joncinque joncinque added the v1.16 PRs that should be backported to v1.16 label Aug 2, 2023
@joncinque joncinque deleted the borsh-0.9 branch August 2, 2023 21:15
mergify bot pushed a commit that referenced this pull request Aug 2, 2023
* sdk: Implement Borsh 0.9 traits on Pubkey

* Alphabetize cargo.toml

* Add backwards-compatible borsh file

* Add borsh0_10.rs for more clarity

* Deprecate `borsh` utils, use borsh0_10 everywhere

* Mark borsh 0.9 helpers as deprecated

* Add macros for deriving helper impls

* Add borsh 0.9 tests

* Refactor tests into macro

(cherry picked from commit 8c14886)

# Conflicts:
#	sdk/src/lib.rs
joncinque added a commit that referenced this pull request Aug 4, 2023
#32511) (#32697)

* sdk: Limited Borsh 0.9 support (Pubkey and helpers) (#32511)

* sdk: Implement Borsh 0.9 traits on Pubkey

* Alphabetize cargo.toml

* Add backwards-compatible borsh file

* Add borsh0_10.rs for more clarity

* Deprecate `borsh` utils, use borsh0_10 everywhere

* Mark borsh 0.9 helpers as deprecated

* Add macros for deriving helper impls

* Add borsh 0.9 tests

* Refactor tests into macro

(cherry picked from commit 8c14886)

# Conflicts:
#	sdk/src/lib.rs

* Fix merge conflict on re-exports

---------

Co-authored-by: Jon Cinque <me@jonc.dev>
grooviegermanikus added a commit to grooviegermanikus/mango-v4 that referenced this pull request Sep 11, 2023
grooviegermanikus added a commit to blockworks-foundation/mango-feeds that referenced this pull request Sep 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v1.16 PRs that should be backported to v1.16
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants