-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
fix: serializing transactions; sort that takes less time and memory #25642
fix: serializing transactions; sort that takes less time and memory #25642
Conversation
@@ -395,13 +395,16 @@ export class Transaction { | |||
|
|||
// Sort. Prioritizing first by signer, then by writable | |||
uniqueMetas.sort(function (x, y) { | |||
const pubkeySorting = x.pubkey | |||
.toBase58() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One string created here.
@@ -395,13 +395,16 @@ export class Transaction { | |||
|
|||
// Sort. Prioritizing first by signer, then by writable | |||
uniqueMetas.sort(function (x, y) { | |||
const pubkeySorting = x.pubkey | |||
.toBase58() | |||
.localeCompare(y.pubkey.toBase58()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another string created here.
const checkSigner = x.isSigner === y.isSigner ? 0 : x.isSigner ? -1 : 1; | ||
const checkWritable = | ||
x.isWritable === y.isWritable ? pubkeySorting : x.isWritable ? -1 : 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CPU and memory that we consumed to produce base58 strings gets thrown out here if the signedness or writability of the accounts differ.
Codecov Report
@@ Coverage Diff @@
## master solana-labs/solana#25642 +/- ##
=======================================
Coverage 75.4% 75.4%
=======================================
Files 40 40
Lines 2344 2345 +1
Branches 337 338 +1
=======================================
+ Hits 1768 1769 +1
Misses 459 459
Partials 117 117 |
Kind of an aside, but lots of (most?) pubkeys get created from base58 strings. What if we kept the string representation and just return it when asked? |
In general I think I love that idea. It seems that pubkeys are used for display and comparison frequently, but signing transactions infrequently. We should probably keep them in base58 in userspace. We can validate strings that purport to be base58 then assign them an opaque TypeScript type (see principle 4 where I used |
(But I get what you're talking about here, specifically, is memoization of |
Yeah, exactly. I think somewhere downstream of the constructor we could save the base58 representation if provided, and if not, memoize it the first time it's needed. This could speed up a ton of apps (like Metaplex) that perform lots of string comparisons this way. |
Yeah, let's do it. Trading memory for CPU is for sure the right thing to do for now. I wish there was an easy way to observe the ecosystem effect of changes like that. Make it faster. Did it matter? Who could know, without data. |
It appears that commits 58092f7, 1727ca4, and 20f169c changed the serialization of transactions in a breaking fashion. v1.43.4 produces a different message for some transactions than v1.43.2, causing signature verification to fail. I think they may need to be reverted while we figure out what changed. |
Base64 encoded serialized transaction on v1.43.2:
Base64 encoded serialized transaction on v1.43.4:
|
Yep. This sort algorithm changed the sort order of accounts.
|
Problem
When compiling messages, we sort accounts. The sort involves producing and comparing pubkey strings, which takes time and memory.
Summary of Changes
isSigner
andisWriteable
alone.cmp
method scans the 8-bit words in big-endian order and bails as soon as it finds that one is larger than the other.Test plan
Run the tests in
transaction.test.ts
. Sort orders still the same.