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

refactor(experimental): implement getBase58EncodedAddressForSeed #1563

Merged
merged 2 commits into from
Sep 7, 2023

Conversation

2501babe
Copy link
Member

@2501babe 2501babe commented Sep 2, 2023

doing this now because its a blocker for me. straightforward reimpl of createWithSeed:

  static async createWithSeed(
    fromPublicKey: PublicKey,
    seed: string,
    programId: PublicKey,
  ): Promise<PublicKey> {
    const buffer = Buffer.concat([
      fromPublicKey.toBuffer(),
      Buffer.from(seed),
      programId.toBuffer(),
    ]);
    const publicKeyBytes = sha256(buffer);
    return new PublicKey(publicKeyBytes);
  }

not ready to merge as-is, pls let me know:

  • how to run lint:fix, theres no command for it so i have no idea
  • if you want this in a new file
  • any style complaints, i tried to copy existing code as much as possible

Closes #999.

@buffalojoec
Copy link
Collaborator

  • how to run lint:fix, theres no command for it so i have no idea

This works from root:

pnpm eslint --fix packages/addresses/src/__tests__/base58-test.ts

Curious what you think of createBase58AddressWithSeed? To match original

@2501babe
Copy link
Member Author

2501babe commented Sep 4, 2023

This works from root

this doesnt run the other linter... it turns out the command was pnpm prettier -w src/base58.ts. if theres a way to run both linters on all files in write mode, that would be a worthwhile command to add to toplevel package.json

Curious what you think of createBase58AddressWithSeed? To match original

sounds good!

@2501babe 2501babe marked this pull request as ready for review September 4, 2023 12:56
@2501babe 2501babe force-pushed the 20230902_seed branch 3 times, most recently from ab0535c to bdda9c5 Compare September 4, 2023 13:22
Copy link
Collaborator

@buffalojoec buffalojoec left a comment

Choose a reason for hiding this comment

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

This looks good and definitely matches the legacy library's implementation, however I wonder why the legacy lib doesn't look more like the Rust side of things.

https://github.com/solana-labs/solana/blob/adee97fe38b175ae185d34a7aa71b2e7bfd570e8/sdk/program/src/pubkey.rs#L206-L224

Why doesn't it have the checks that solana_program does (MAX_SEED_LENGTH, PDA_MARKER), any idea?

I think we should probably add these checks even though they weren't originally there, unless we have good reason not to.

@steveluscher
Copy link
Collaborator

Hang on one sec before you ship this. I’ll make some suggestions tomorrow.

Copy link
Collaborator

@steveluscher steveluscher left a comment

Choose a reason for hiding this comment

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

…I wonder why the legacy lib doesn't look more like the Rust side of things.

Yeah, 100%. I remember seeing that code and being like ‘hmm, we should roll that in.’ Add to this implementation:

  • A check for max seed length like we did for program-derived-address (add tests)
  • The Rust-style check for a forged PDA marker. What you're trying to protect against is this super weird edge case: create(baseAddress, seed, '4vJ9JU1bJJE96FbKdjWme2JfVK1knU936FHTDZV7AC2'). The last 21 bytes of 4vJ9JU1bJJE96FbKdjWme2JfVK1knU936FHTDZV7AC2 just happen to decode to the ASCII string ProgramDerivedAddress. (add tests)

Just one other thought: I think this is one of those APIs where a struct arg would be better. See createProgramDerivedAddress(pdaInput: PdaInput).

programAddress: Base58EncodedAddress
): Promise<Base58EncodedAddress> {
const { serialize, deserialize } = getBase58EncodedAddressCodec();
const seedBytes = new TextEncoder().encode(seed);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I was going to point out that TextEncoder isn't available in React Native, but:

  • We also use it in program-derived-address.ts
  • We should presume that, in React Native, we need to call out to an async API to do this encoding, but you've already made this method async so… carry on.

@@ -132,4 +133,16 @@ describe('base58', () => {
]);
});
});
describe('createBase58AddressWithSeed', () => {
it('works', async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

For the benefit of the next reader who doesn't know what this is supposed to do in the first place.

Suggested change
it('works', async () => {
it('returns an address that is the SHA-256 hash of the concatenated base address, seed, and program address', async () => {

@@ -52,3 +52,18 @@ export function getBase58EncodedAddressComparator(): (x: string, y: string) => n
usage: 'sort',
}).compare;
}

export async function createBase58AddressWithSeed(
Copy link
Collaborator

Choose a reason for hiding this comment

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

For pedantry:

Suggested change
export async function createBase58AddressWithSeed(
export async function createBase58EncodedAddressWithSeed(

Copy link
Collaborator

Choose a reason for hiding this comment

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

Akshually; I just renamed everything to *Address* didn't I? So createAddressWithSeed is the thing that would match everything else now.

@2501babe
Copy link
Member Author

2501babe commented Sep 7, 2023

ok i

  • renamed the function to createAddressWithSeed
  • gave it an args struct
  • renamed program-derived-address*.ts to computed-address*.ts and moved the functionality there since they both require the same constants and have a certain harmony
  • added guardrails as in rust and tests for them

@2501babe
Copy link
Member Author

2501babe commented Sep 7, 2023

note ci failure is due to a bug in node nodejs/node#49497

Copy link
Collaborator

@steveluscher steveluscher left a comment

Choose a reason for hiding this comment

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

giphy-7

@steveluscher steveluscher merged commit 5030000 into solana-labs:master Sep 7, 2023
3 of 6 checks passed
@github-actions
Copy link
Contributor

🎉 This PR is included in version 1.78.5 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions
Copy link
Contributor

Because there has been no activity on this PR for 14 days since it was merged, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 27, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make PublicKey.createWithSeed (js) same as create_with_seed in runtime to avoid confusion
3 participants