-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7a7c986
Showing
13 changed files
with
1,563 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
.anchor | ||
.DS_Store | ||
target | ||
**/*.rs.bk | ||
node_modules | ||
test-ledger |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
.anchor | ||
.DS_Store | ||
target | ||
node_modules | ||
dist | ||
build | ||
test-ledger |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[features] | ||
seeds = false | ||
skip-lint = false | ||
[programs.localnet] | ||
bump_seed_canonicalization = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS" | ||
|
||
[registry] | ||
url = "https://api.apr.dev" | ||
|
||
[provider] | ||
cluster = "localnet" | ||
wallet = "/home/ixmorrow/.config/solana/id.json" | ||
|
||
[scripts] | ||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[workspace] | ||
members = [ | ||
"programs/*" | ||
] | ||
|
||
[profile.release] | ||
overflow-checks = true | ||
lto = "fat" | ||
codegen-units = 1 | ||
[profile.release.build-override] | ||
opt-level = 3 | ||
incremental = false | ||
codegen-units = 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Migrations are an early feature. Currently, they're nothing more than this | ||
// single deploy script that's invoked from the CLI, injecting a provider | ||
// configured from the workspace's Anchor.toml. | ||
|
||
const anchor = require("@project-serum/anchor"); | ||
|
||
module.exports = async function (provider) { | ||
// Configure client to use the provider. | ||
anchor.setProvider(provider); | ||
|
||
// Add your deploy script here. | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"scripts": { | ||
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", | ||
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" | ||
}, | ||
"dependencies": { | ||
"@project-serum/anchor": "^0.25.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.3.4", | ||
"mocha": "^9.0.3", | ||
"ts-mocha": "^10.0.0", | ||
"@types/bn.js": "^5.1.0", | ||
"@types/chai": "^4.3.0", | ||
"@types/mocha": "^9.0.0", | ||
"typescript": "^4.3.5", | ||
"prettier": "^2.6.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
[package] | ||
name = "bump-seed-canonicalization" | ||
version = "0.1.0" | ||
description = "Created with Anchor" | ||
edition = "2021" | ||
|
||
[lib] | ||
crate-type = ["cdylib", "lib"] | ||
name = "bump_seed_canonicalization" | ||
|
||
[features] | ||
no-entrypoint = [] | ||
no-idl = [] | ||
no-log-ix-name = [] | ||
cpi = ["no-entrypoint"] | ||
default = [] | ||
|
||
[dependencies] | ||
anchor-lang = "0.25.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[target.bpfel-unknown-unknown.dependencies.std] | ||
features = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
use anchor_lang::prelude::*; | ||
use borsh::{BorshDeserialize, BorshSerialize}; | ||
|
||
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"); | ||
|
||
#[program] | ||
pub mod bump_seed_canonicalization { | ||
use super::*; | ||
|
||
// insecure, allows for creation of multiple accounts for given set of seeds | ||
pub fn initialize(ctx: Context<Initialize>, bump_seed: u8) -> Result<()> { | ||
let space = 32; | ||
let lamports = Rent::get()?.minimum_balance(space as usize); | ||
|
||
let ix = anchor_lang::solana_program::system_instruction::create_account( | ||
&ctx.accounts.payer.key(), | ||
&ctx.accounts.pda.key(), | ||
lamports, | ||
space, | ||
&ctx.program_id, | ||
); | ||
|
||
anchor_lang::solana_program::program::invoke_signed( | ||
&ix, | ||
&[ | ||
ctx.accounts.payer.to_account_info(), | ||
ctx.accounts.pda.to_account_info(), | ||
ctx.accounts.system_program.to_account_info(), | ||
], | ||
&[&[&[bump_seed]]], | ||
)?; | ||
|
||
let mut account = User::try_from_slice(&ctx.accounts.pda.data.borrow()).unwrap(); | ||
|
||
account.user = ctx.accounts.payer.key(); | ||
account.serialize(&mut *ctx.accounts.pda.data.borrow_mut())?; | ||
|
||
msg!("PDA: {}", ctx.accounts.pda.key()); | ||
msg!("User: {}", account.user); | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn insecure(ctx: Context<Unchecked>, bump_seed: u8) -> Result<()> { | ||
let address = Pubkey::create_program_address(&[&[bump_seed]], ctx.program_id).unwrap(); | ||
if address != ctx.accounts.pda.key() { | ||
return Err(ProgramError::InvalidArgument.into()); | ||
} | ||
|
||
let account = User::try_from_slice(&ctx.accounts.pda.data.borrow()).unwrap(); | ||
|
||
msg!("PDA: {}", ctx.accounts.pda.key()); | ||
msg!("User: {}", account.user); | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[derive(Accounts)] | ||
pub struct Initialize<'info> { | ||
#[account(mut)] | ||
/// CHECK: | ||
pub pda: AccountInfo<'info>, | ||
#[account(mut)] | ||
pub payer: Signer<'info>, | ||
pub system_program: Program<'info, System>, | ||
} | ||
|
||
#[derive(Accounts)] | ||
pub struct Unchecked<'info> { | ||
/// CHECK: | ||
pda: AccountInfo<'info>, | ||
} | ||
|
||
#[derive(Accounts)] | ||
pub struct Checked<'info> { | ||
#[account(seeds = [], bump)] | ||
pda: Account<'info, UserAccount>, | ||
} | ||
|
||
#[derive(BorshSerialize, BorshDeserialize, Clone)] | ||
pub struct User { | ||
user: Pubkey, | ||
} | ||
|
||
// Anchor account | ||
#[account] | ||
pub struct Data { | ||
value: u64, | ||
// bump field | ||
bump: u8 | ||
} | ||
|
||
|
||
|
||
/* ************************************************************ */ | ||
|
||
pub const DATA_PDA_SEED: &str = "test-seed"; | ||
|
||
#[derive(Clone)] | ||
pub struct UserAccount(User); | ||
|
||
impl anchor_lang::Owner for UserAccount { | ||
fn owner() -> Pubkey { | ||
ID | ||
} | ||
} | ||
|
||
impl anchor_lang::AccountSerialize for UserAccount {} | ||
|
||
impl anchor_lang::AccountDeserialize for UserAccount { | ||
fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result<Self> { | ||
User::deserialize(buf).map(Self).map_err(Into::into) | ||
} | ||
|
||
fn try_deserialize(buf: &mut &[u8]) -> Result<Self> { | ||
Self::try_deserialize_unchecked(buf) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import * as anchor from "@project-serum/anchor" | ||
import { Program } from "@project-serum/anchor" | ||
import { | ||
findProgramAddressSync, | ||
} from "@project-serum/anchor/dist/cjs/utils/pubkey" | ||
import { expect } from "chai" | ||
import { BumpSeedCanonicalization } from "../target/types/bump_seed_canonicalization" | ||
import { PublicKey, Keypair, SystemProgram } from '@solana/web3.js' | ||
import { safeAirdrop, findNonCanonicalPda } from './utils/utils' | ||
import { BN } from "bn.js" | ||
|
||
describe("bump-seed-canonicalization", async () => { | ||
// Initialize testing environment | ||
anchor.setProvider(anchor.AnchorProvider.env()) | ||
const provider = anchor.AnchorProvider.env() | ||
const program = anchor.workspace.BumpSeedCanonicalization as Program<BumpSeedCanonicalization> | ||
|
||
// payer for creation of accounts | ||
const payer = Keypair.generate() | ||
|
||
// derive first PDA using canonical bump | ||
const [pda, bump] = findProgramAddressSync([], program.programId) | ||
console.log("First canonical PDA:", pda.toString()) | ||
console.log("Canonical bump:", bump) | ||
|
||
// derive second PDA using a non-canonical bump | ||
const [pda_not_canonical, not_canonical_bump] = await findNonCanonicalPda( | ||
[], | ||
program.programId | ||
) | ||
console.log("First non-canonical PDA:", pda_not_canonical.toString()) | ||
console.log("Non-canonical bump:", not_canonical_bump) | ||
|
||
|
||
it("Initialize PDA using canonical bump", async () => { | ||
await program.methods.initialize(bump).accounts({ pda: pda }).rpc() | ||
}) | ||
|
||
it("Initialize PDA using non-canonical bump", async () => { | ||
await program.methods | ||
.initialize(not_canonical_bump) | ||
.accounts({ pda: pda_not_canonical }) | ||
.rpc() | ||
}) | ||
|
||
it("Verify PDA with canonical bump", async () => { | ||
await program.methods.insecure(bump).accounts({ pda: pda }).rpc() | ||
}) | ||
|
||
it("Verify PDA with non-canonical bump", async () => { | ||
await program.methods | ||
.insecure(not_canonical_bump) | ||
.accounts({ pda: pda_not_canonical }) | ||
.rpc() | ||
}) | ||
|
||
// it("Create new account with canonnical bump via Anchor constraints", async () => { | ||
// // payer needs SOL to pay for account creation | ||
// await safeAirdrop(payer.publicKey, provider.connection) | ||
|
||
// const pda_seed = "test-seed" | ||
// const value = 55 | ||
// const [pda_canonical, canonical_bump] = await PublicKey.findProgramAddress( | ||
// [Buffer.from(pda_seed)], | ||
// program.programId | ||
// ) | ||
|
||
// console.log("Second canonical PDA:", pda_canonical.toString()) | ||
// console.log("Canonical bump:", canonical_bump) | ||
|
||
// await program.methods.initializeWithAnchor(new BN(value)) | ||
// .accounts({ | ||
// payer: payer.publicKey, | ||
// data: pda_canonical, | ||
// systemProgram: SystemProgram.programId | ||
// }) | ||
// .signers([payer]) | ||
// .rpc() | ||
// }) | ||
|
||
// // this test should fail because Anchor will not initalize an account at a PDA that is not derived with the canonical bump | ||
// it("Create new account with non-canonnical bump via Anchor constraints (should fail)", async () => { | ||
// // same seed as test above | ||
// const pda_seed = "test-seed" | ||
// // derive PDA using the same seed as before, but use a different bump that is not the canonical bump | ||
// const [non_canonical_pda, non_canonical_bump] = await findNonCanonicalPda( | ||
// [Buffer.from(pda_seed)], | ||
// program.programId | ||
// ) | ||
// console.log("Second non-canonical PDA:", non_canonical_pda.toString()) | ||
// console.log("Non-canonical bump:", non_canonical_bump) | ||
// try { | ||
// await program.methods.initializeWithAnchor(new BN(non_canonical_bump)) | ||
// .accounts({ | ||
// payer: payer.publicKey, | ||
// data: non_canonical_pda, | ||
// systemProgram: SystemProgram.programId | ||
// }) | ||
// .signers([payer]) | ||
// .rpc() | ||
// } catch (e) { | ||
// console.log(e.message) | ||
// expect(e.message).to.eq("failed to send transaction: Transaction simulation failed: Error processing Instruction 0: Cross-program invocation with unauthorized signer or writable account") | ||
// } | ||
// }) | ||
|
||
// it("Verify address of account PDA via Anchor constraints with canonical bump", async () => { | ||
// const pda_seed = "test-seed" | ||
// const [pda_canonical, canonical_bump] = await PublicKey.findProgramAddress( | ||
// [Buffer.from(pda_seed)], | ||
// program.programId | ||
// ) | ||
|
||
// await program.methods.verifyAddress() | ||
// .accounts({ | ||
// data: pda_canonical, | ||
// }) | ||
// .rpc() | ||
// }) | ||
|
||
// it("Try to verify address of non-canonical pda (should fail)", async () => { | ||
// const pda_seed = "test-seed" | ||
// const [non_canonical_pda, non_canonical_bump] = await findNonCanonicalPda( | ||
// [Buffer.from(pda_seed)], | ||
// program.programId | ||
// ) | ||
|
||
// try { | ||
// const createAcctTx = await program.methods.verifyAddress() | ||
// .accounts({ | ||
// data: non_canonical_pda, | ||
// }) | ||
// .rpc() | ||
// console.log("Verify PDA account via Anchor constraints: ", createAcctTx) | ||
// } catch (e) { | ||
// console.log(e.message) | ||
// expect(e.message).to.eq("AnchorError caused by account: data. Error Code: AccountNotInitialized. Error Number: 3012. Error Message: The program expected this account to be already initialized.") | ||
// } | ||
// }) | ||
}) |
Oops, something went wrong.