PDA-johdannainen

Yhteenveto

PDA:t johdetaan hajautusarvolla seedit + ohjelmatunniste + bump SHA-256:n kautta, kunnes tulos on Ed25519-käyrän ulkopuolella. Kanoninen bump on ensimmäinen arvo, joka tuottaa käyrän ulkopuolisen osoitteen. Maksimi 16 seediä, maksimi 32 tavua per seedi.

Tausta

Solanan Keypair -arvot ovat pisteitä Ed25519-käyrällä. Avainpari koostuu julkisesta avaimesta (käytetään tilin osoitteena) ja salaisesta avaimesta (käytetään allekirjoitusten tuottamiseen). Kuka tahansa, jolla on salainen avain, voi allekirjoittaa transaktioita kyseiselle osoitteelle.

Kaksi tiliä käyrällä olevilla osoitteillaKaksi tiliä käyrällä olevilla osoitteilla

PDA johdetaan tarkoituksella putoamaan Ed25519-käyrän ulkopuolelle. Koska se ei ole kelvollinen käyräpiste, salaista avainta ei ole olemassa, eikä mikään ulkopuolinen taho voi tuottaa allekirjoitusta. Vain johdattava ohjelma voi valtuuttaa operaatioita PDA:lla invoke_signed:n kautta.

Käyrän ulkopuolinen osoiteKäyrän ulkopuolinen osoite

PDA vs avainparitilit

OminaisuusAvainparitiliPDA-tili
OsoitetyyppiEd25519-käyrälläEd25519-käyrän ulkopuolella
On yksityinen avainKylläEi
Voi allekirjoittaa transaktioitaKyllä (yksityisellä avaimella)Ei
Voi allekirjoittaa CPI:n aikanaEi (ellei allekirjoitusta sisällytetä transaktioon)Kyllä (invoke_signed:n kautta)
JohdannainenGeneroi Ed25519-avainpariDeterministinen seediistä + ohjelmatunnisteesta
Tyypillinen käyttöKäyttäjälompakot, ohjelmatunnisteOhjelman omistamat datatilit

Valinnaiset siemenet

Valinnaiset siemenet ovat käyttäjän määrittämiä tavujonoja, jotka toimivat syötteinä PDA-johdannaiselle. Ne luovat ainutlaatuisia, deterministisiä osoitteita, jotka on rajattu ohjelmaan. Esimerkiksi ["user", user_pubkey]:n käyttäminen siemeninä johtaa eri PDA:han jokaiselle käyttäjälle.

Siementen on noudatettava seuraavia rajoituksia:

  • Enintään 16 siementä johdannaista kohti (MAX_SEEDS)
  • Enintään 32 tavua siementä kohti (MAX_SEED_LEN)

Bump seed

Bump seed on yksittäinen tavu (0-255), joka liitetään valinnaisten siementen perään johdannaisen aikana. find_program_address etsii arvosta 255 alaspäin arvoon 0, kutsuen create_program_address:a jokaisella arvolla, kunnes tulos putoaa Ed25519-käyrän ulkopuolelle. Ensimmäinen onnistunut arvo on kanoninen bump.

Ohjelmien tulisi aina käyttää kanonista bumpia varmistaakseen ainutlaatuisen, deterministisen yhdistämisen siemenistä osoitteeseen.

Käytä aina kanonista bumpia johdettaessa PDA:ita. Ei-kanonisen bumpin käyttäminen luo toisen kelvollisen osoitteen samoille siemenille, mikä voi johtaa haavoittuvuuksiin, joissa hyökkääjä korvaa odotetun tilin toisella.

PDA-johdannainenPDA-johdannainen

Johdannaisalgoritmi

PDA-johdannainen on toteutettu SDK:n create_program_address-funktiossa. Algoritmi toimii seuraavasti:

  1. Validoi, että siementen määrä ei ylitä MAX_SEEDS:a (16) eikä yksittäinen siemen ylitä MAX_SEED_LEN:a (32 tavua). Jos jompikumpi tarkistus epäonnistuu, palauta PubkeyError::MaxSeedLengthExceeded.
  2. SHA-256-hajautusarvo kaikista siemenistä, ohjelmatunnuksesta ja merkkijonosta "ProgramDerivedAddress" yhdessä tuottaaksesi 32-tavuisen tuloksen.
  3. Tarkista, onko tulos kelvollinen piste Ed25519-käyrällä.
  4. Jos tulos ON käyrällä, palauta PubkeyError::InvalidSeeds (osoitteella olisi vastaava yksityinen avain, mikä rikkoo PDA:n turvallisuusominaisuutta).
  5. Jos tulos EI ole käyrällä, palauta se PDA:na.

Laskentayksikkökustannukset

Ketjussa oleva syscall create_program_address-toiminnolle veloittaa 1 500 CU:ta per kutsu.

try_find_program_address syscall veloittaa 1 500 CU:ta alussa (ennen silmukkaa), ja sen jälkeen ylimääräiset 1 500 CU:ta jokaisesta epäonnistuneesta bump-yrityksestä silmukan sisällä.

Yleiset seed-mallit

Seedit ovat sovelluskohtaisia. Yleisiä malleja ovat:

MalliSeeditKäyttötapaus
Globaali singleton["global"]Yksittäinen ohjelman laajuinen konfiguraatiotili
Käyttäjäkohtainen tili["user", user_pubkey]Yksi tili per käyttäjä per ohjelma
Käyttäjä-entiteetti-kohtainen["vault", user_pubkey, mint_pubkey]Token-holvit, per käyttäjä per token
Laskuri / peräkkäinen["order", user_pubkey, &order_id.to_le_bytes()]Peräkkäiset tietueet per käyttäjä

Seedit yhdistetään ennen hajautusta, joten ["ab", "cd"] ja ["abcd"] tuottavat saman PDA:n. Käytä kiinteän pituisia seedejä tai erotinta välttääksesi törmäykset. Esimerkiksi ["ab", "-", "cd"] on yksiselitteinen.

Esimerkit: PDA:n johdattaminen

PDA:n johdattaminen laskee vain osoitteen. Se ei luo ketjussa olevaa tiliä kyseiseen osoitteeseen. Tili on luotava erikseen erillisellä instruktiolla (tyypillisesti create_account CPI:n kautta).

Solana SDK:t tarjoavat funktioita PDA:n johdattamiseen. Jokainen funktio ottaa:

  • Program ID: Ohjelman osoite, jota käytetään PDA:n johdattamiseen. Tämä ohjelma voi allekirjoittaa PDA:n puolesta.
  • Valinnaiset seedit: Ennalta määritellyt syötteet, kuten merkkijonot, numerot tai muut tilien osoitteet.
SDKFunktio
@solana/kit (TypeScript)getProgramDerivedAddress
@solana/web3.js (TypeScript)findProgramAddressSync
solana_sdk (Rust)find_program_address

Alla olevat esimerkit johdattavat PDA:n käyttäen Solana SDK:ita. Napsauta ▷ Suorita suorittaaksesi koodin.

Johda PDA merkkijonoseedillä

Alla oleva esimerkki johtaa PDA:n käyttäen ohjelma-ID:tä ja valinnaista merkkijonoseedä.

import { Address, getProgramDerivedAddress } from "@solana/kit";
const programAddress = "11111111111111111111111111111111" as Address;
const seeds = ["helloWorld"];
const [pda, bump] = await getProgramDerivedAddress({
programAddress,
seeds
});
console.log(`PDA: ${pda}`);
console.log(`Bump: ${bump}`);
Console
Click to execute the code.

Johda PDA osoiteseedillä

Alla oleva esimerkki johtaa PDA:n käyttäen ohjelma-ID:tä ja valinnaista osoiteseedä.

import {
Address,
getAddressEncoder,
getProgramDerivedAddress
} from "@solana/kit";
const programAddress = "11111111111111111111111111111111" as Address;
const addressEncoder = getAddressEncoder();
const optionalSeedAddress = addressEncoder.encode(
"B9Lf9z5BfNPT4d5KMeaBFx8x1G4CULZYR1jA2kmxRDka" as Address
);
const seeds = [optionalSeedAddress];
const [pda, bump] = await getProgramDerivedAddress({
programAddress,
seeds
});
console.log(`PDA: ${pda}`);
console.log(`Bump: ${bump}`);
Console
Click to execute the code.

Johda PDA useilla seedeillä

Alla oleva esimerkki johtaa PDA:n käyttäen ohjelma-ID:tä ja useita valinnaisia seedejä.

import {
Address,
getAddressEncoder,
getProgramDerivedAddress
} from "@solana/kit";
const programAddress = "11111111111111111111111111111111" as Address;
const optionalSeedString = "helloWorld";
const addressEncoder = getAddressEncoder();
const optionalSeedAddress = addressEncoder.encode(
"B9Lf9z5BfNPT4d5KMeaBFx8x1G4CULZYR1jA2kmxRDka" as Address
);
const seeds = [optionalSeedString, optionalSeedAddress];
const [pda, bump] = await getProgramDerivedAddress({
programAddress,
seeds
});
console.log(`PDA: ${pda}`);
console.log(`Bump: ${bump}`);
Console
Click to execute the code.

Kaikkien bumpien iterointi

Seuraavat esimerkit näyttävät PDA:n johtamisen käyttäen kaikkia mahdollisia bump-seedejä (255:stä 0:aan), havainnollistaen kuinka find_program_address palauttaa kanonisen bumpin:

Kit-esimerkkiä ei ole mukana, koska createProgramDerivedAddress-funktiota ei ole viety.

import { PublicKey } from "@solana/web3.js";
const programId = new PublicKey("11111111111111111111111111111111");
const optionalSeed = "helloWorld";
// Loop through all bump seeds (255 down to 0)
for (let bump = 255; bump >= 0; bump--) {
try {
const PDA = PublicKey.createProgramAddressSync(
[Buffer.from(optionalSeed), Buffer.from([bump])],
programId
);
console.log("bump " + bump + ": " + PDA);
} catch (error) {
console.log("bump " + bump + ": " + error);
}
}
Console
Click to execute the code.
bump 255: Error: Invalid seeds, address must fall off the curve
bump 254: 46GZzzetjCURsdFPb7rcnspbEMnCBXe9kpjrsZAkKb6X
bump 253: GBNWBGxKmdcd7JrMnBdZke9Fumj9sir4rpbruwEGmR4y
bump 252: THfBMgduMonjaNsCisKa7Qz2cBoG1VCUYHyso7UXYHH
bump 251: EuRrNqJAofo7y3Jy6MGvF7eZAYegqYTwH2dnLCwDDGdP
bump 250: Error: Invalid seeds, address must fall off the curve
...
// remaining bump outputs

Tässä esimerkissä bump 255 tuottaa käyrällä olevan osoitteen ja epäonnistuu. Ensimmäinen kelvollinen bump on 254, mikä tekee siitä kanonisen bumpin.

Is this page helpful?

Sisällysluettelo

Muokkaa sivua

Hallinnoi

© 2026 Solana Foundation.
Kaikki oikeudet pidätetään.
Yhdistä