Op Solana wordt een smart contract een programma genoemd. Een programma is een stateless account dat uitvoerbare code bevat. Deze code is georganiseerd in functies die instructies worden genoemd. Gebruikers communiceren met een programma door een transactie te verzenden die één of meer instructies bevat. Een transactie kan instructies van meerdere programma's bevatten.
Wanneer een programma wordt geïmplementeerd, gebruikt Solana LLVM om het te compileren naar executable and linkable format (ELF). Het ELF-bestand bevat de binary van het programma in Solana Bytecode Format (sBPF) en wordt on-chain opgeslagen in een uitvoerbaar account.
sBPF is Solana's aangepaste versie van eBPF bytecode.
Programma's schrijven
De meeste programma's zijn geschreven in Rust, met twee veelvoorkomende ontwikkelbenaderingen:
- Anchor: Anchor is een framework ontworpen voor snelle en eenvoudige Solana-ontwikkeling. Het gebruikt Rust-macro's om boilerplate-code te verminderen—ideaal voor beginners.
- Native Rust: schrijf programma's in Rust zonder gebruik te maken van frameworks. Deze benadering biedt meer flexibiliteit maar gaat gepaard met toegenomen complexiteit.
Programma's updaten
Om een bestaand programma te
wijzigen,
moet een account worden aangewezen als de
upgrade authority.
(Doorgaans hetzelfde account dat het programma oorspronkelijk heeft
geïmplementeerd.) Als de upgrade authority wordt
ingetrokken en ingesteld op None, kan het programma niet meer worden
geüpdatet.
Programma's verifiëren
Solana ondersteunt verifieerbare builds, waarmee gebruikers kunnen controleren of de on-chain code van een programma overeenkomt met de publieke broncode. Het Anchor-framework biedt ingebouwde ondersteuning voor het creëren van een verifieerbare build.
Om te controleren of een bestaand programma geverifieerd is, zoek je naar de programma-ID op de Solana Explorer. Als alternatief kun je de Ellipsis Labs Solana Verifiable Build CLI gebruiken om on-chain programma's onafhankelijk te verifiëren.
Ingebouwde programma's
Het System Program
Het System Program is het enige account dat nieuwe accounts kan aanmaken. Standaard zijn alle nieuwe accounts eigendom van het System Program, hoewel veel ervan bij het aanmaken een nieuwe eigenaar toegewezen krijgen. Het System Program voert de volgende kernfuncties uit:
| Functie | Beschrijving |
|---|---|
| Nieuwe account aanmaken | Alleen het System Program kan nieuwe accounts aanmaken. |
| Ruimte toewijzen | Stelt de bytecapaciteit in voor het dataveld van elk account. |
| Programma-eigendom toewijzen | Nadat het System Program een account heeft aangemaakt, kan het de aangewezen programma-eigenaar opnieuw toewijzen aan een ander programma-account. Zo nemen aangepaste programma's eigendom over van nieuwe accounts die door het System Program zijn aangemaakt. |
| SOL overdragen | Draagt lamports (SOL) over van systeemaccounts naar andere accounts. |
Het adres van het System Program is 11111111111111111111111111111111.
Loader-programma's
Elk programma is eigendom van een ander programma: de loader. Loaders worden gebruikt om programma's te deployen, te herdeployen, te upgraden of te sluiten. Ze worden ook gebruikt om een programma af te ronden en programma-autoriteit over te dragen.
Er zijn momenteel vijf loader-programma's, zoals weergegeven in onderstaande tabel.
| Loader | Programma-ID | Opmerkingen | Instructies link |
|---|---|---|---|
| native | NativeLoader1111111111111111111111111111111 | Bezit de andere vier loaders | — |
| v1 | BPFLoader1111111111111111111111111111111111 | Beheerinstructies zijn uitgeschakeld, maar programma's worden nog steeds uitgevoerd | — |
| v2 | BPFLoader2111111111111111111111111111111111 | Beheerinstructies zijn uitgeschakeld, maar programma's worden nog steeds uitgevoerd | Instructies |
| v3 | BPFLoaderUpgradeab1e11111111111111111111111 | Programma's kunnen na deployment worden bijgewerkt. Uitvoerbaar programma wordt opgeslagen in een apart programdata-account | Instructies |
| v4 | LoaderV411111111111111111111111111111111111 | In ontwikkeling (nog niet uitgebracht) | Instructies |
Programma's die zijn geïmplementeerd met loader-v3 of loader-v4 kunnen na implementatie worden aangepast, zoals bepaald door de upgrade authority.
Wanneer een nieuw programma wordt geïmplementeerd, wordt standaard de nieuwste loader-versie gebruikt.
Voorgecompileerde programma's
Naast de loader-programma's biedt Solana de volgende voorgecompileerde programma's.
Verifieer ed25519-handtekening
Het ed25519-programma wordt gebruikt om een of meer ed25519-handtekeningen te verifiëren.
| Programma | Programma-ID | Beschrijving | Instructies |
|---|---|---|---|
| Ed25519 Programma | Ed25519SigVerify111111111111111111111111111 | Verifieert ed25519-handtekeningen. Als een handtekening mislukt, wordt een fout geretourneerd. | Instructies |
Het ed25519-programma verwerkt een instructie. De eerste u8 van de instructie
bevat een telling van het aantal handtekeningen dat moet worden gecontroleerd,
gevolgd door een enkele byte padding. Daarna wordt de volgende struct
geserialiseerd, een voor elke handtekening die moet worden gecontroleerd.
struct Ed25519SignatureOffsets {signature_offset: u16, // offset to ed25519 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to public key of 32 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionsinstruction_index = ed25519_signature_instruction_index != u16::MAX ? ed25519_signature_instruction_index : current_instruction;signature = instructions[instruction_index].data[ed25519_signature_offset..ed25519_signature_offset + 64]instruction_index = ed25519_pubkey_instruction_index != u16::MAX ? ed25519_pubkey_instruction_index : current_instruction;pubkey = instructions[instruction_index].data[ed25519_pubkey_offset..ed25519_pubkey_offset + 32]instruction_index = ed25519_message_instruction_index != u16::MAX ? ed25519_message_instruction_index : current_instruction;message = instructions[instruction_index].data[ed25519_message_data_offset..ed25519_message_data_offset + ed25519_message_data_size]if pubkey.verify(signature, message) != Success {return Error}}return Success}
Verifieer secp256k1-herstel
Het secp256k1-programma wordt gebruikt om secp256k1 public key recovery-operaties te verifiëren.
| Programma | Programma-ID | Beschrijving | Instructies |
|---|---|---|---|
| Secp256k1 Programma | KeccakSecp256k11111111111111111111111111111 | Verifieert secp256k1 public key recovery-operaties (ecrecover). | Instructies |
Het secp256k1-programma verwerkt een instructie. De eerste byte van de instructie bevat een telling van het aantal publieke sleutels dat moet worden gecontroleerd. Daarna wordt de volgende struct eenmaal voor elke publieke sleutel aangemaakt, vervolgens geserialiseerd en toegevoegd aan de instruction data.
struct Secp256k1SignatureOffsets {secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytessecp_signature_instruction_index: u8, // instruction index to find signaturesecp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytessecp_pubkey_instruction_index: u8, // instruction index to find pubkeysecp_message_data_offset: u16, // offset to start of message datasecp_message_data_size: u16, // size of message datasecp_message_instruction_index: u8, // instruction index to find message data}
process_instruction() {for i in 0..count {// i'th index values referenced:instructions = &transaction.message().instructionssignature = instructions[secp_signature_instruction_index].data[secp_signature_offset..secp_signature_offset + 64]recovery_id = instructions[secp_signature_instruction_index].data[secp_signature_offset + 64]ref_eth_pubkey = instructions[secp_pubkey_instruction_index].data[secp_pubkey_offset..secp_pubkey_offset + 20]message_hash = keccak256(instructions[secp_message_instruction_index].data[secp_message_data_offset..secp_message_data_offset + secp_message_data_size])pubkey = ecrecover(signature, recovery_id, message_hash)eth_pubkey = keccak256(pubkey[1..])[12..]if eth_pubkey != ref_eth_pubkey {return Error}}return Success}
Dit stelt de gebruiker in staat om willekeurige instruction data in de transactie te specificeren voor handtekening- en berichtgegevens. Door een speciale instructions sysvar te specificeren, kan men ook gegevens ontvangen van de transactie zelf.
De kosten van de transactie worden berekend door het aantal te verifiëren handtekeningen te vermenigvuldigen met de handtekeningkostenverificatievermenigvuldiger.
Het secp256r1-programma wordt gebruikt om maximaal 8 secp256r1-handtekeningen te verifiëren.
| Programma | Programma-ID | Beschrijving | Instructies |
|---|---|---|---|
| Secp256r1 Programma | Secp256r1SigVerify1111111111111111111111111 | Verifieert tot 8 secp256r1-handtekeningen. Neemt een handtekening, publieke sleutel en bericht. Retourneert een fout bij mislukking. | Instructies |
Het secp256r1-programma verwerkt een instructie. De eerste u8 van de
instructie is een telling van het aantal handtekeningen dat moet worden
gecontroleerd, gevolgd door een enkele byte padding. Daarna wordt de volgende
struct voor elke handtekening aangemaakt, vervolgens geserialiseerd en
toegevoegd aan de instruction data.
struct Secp256r1SignatureOffsets {signature_offset: u16, // offset to compact secp256r1 signature of 64 bytessignature_instruction_index: u16, // instruction index to find signaturepublic_key_offset: u16, // offset to compressed public key of 33 bytespublic_key_instruction_index: u16, // instruction index to find public keymessage_data_offset: u16, // offset to start of message datamessage_data_size: u16, // size of message datamessage_instruction_index: u16, // index of instruction data to get message data}
Lage S-waarden worden afgedwongen voor alle handtekeningen om onbedoelde handtekeningveranderbaarheid te voorkomen.
process_instruction() {if data.len() < SIGNATURE_OFFSETS_START {return Error}num_signatures = data[0] as usizeif num_signatures == 0 || num_signatures > 8 {return Error}expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_STARTif data.len() < expected_data_size {return Error}for i in 0..num_signatures {offsets = parse_signature_offsets(data, i)signature = get_data_slice(data, instruction_datas, offsets.signature_instruction_index, offsets.signature_offset, SIGNATURE_SERIALIZED_SIZE)if s > half_curve_order {return Error}pubkey = get_data_slice(data, instruction_datas, offsets.public_key_instruction_index, offsets.public_key_offset, COMPRESSED_PUBKEY_SERIALIZED_SIZE)message = get_data_slice(data, instruction_datas, offsets.message_instruction_index, offsets.message_data_offset, offsets.message_data_size)if !verify_signature(signature, pubkey, message) {return Error}}return Success}
Kernprogramma's
De programma's in de onderstaande lijst bieden de kernfunctionaliteit van het netwerk.
| Programma | Programma-ID | Beschrijving | Instructies |
|---|---|---|---|
| System | 11111111111111111111111111111111 | Maak nieuwe accounts aan, wijs accountgegevens toe, ken accounts toe aan eigenaar-programma's, draag lamports over van accounts die eigendom zijn van het System Program, en betaal transactiekosten | SystemInstruction |
| Vote | Vote111111111111111111111111111111111111111 | Maak en beheer accounts die de stemstatus en beloningen van validators bijhouden | VoteInstruction |
| Stake | Stake11111111111111111111111111111111111111 | Maak en beheer accounts die stake en beloningen voor delegaties aan validators vertegenwoordigen | StakeInstruction |
| Config | Config1111111111111111111111111111111111111 | Voeg configuratiegegevens toe aan de chain, gevolgd door de lijst met publieke sleutels die deze mogen wijzigen. In tegenstelling tot de andere programma's definieert het Config-programma geen individuele instructies. Het heeft slechts één impliciete instructie: "store". De instruction data bestaat uit een set sleutels die toegang tot het account en de daarin opgeslagen gegevens regelen | ConfigInstruction |
| Compute Budget | ComputeBudget111111111111111111111111111111 | Stel compute unit-limieten en -prijzen in voor transacties, waardoor gebruikers compute-resources en prioriteringskosten kunnen beheren | ComputeBudgetInstruction |
| Address Lookup Table | AddressLookupTab1e1111111111111111111111111 | Beheer address lookup tables, waarmee transacties naar meer accounts kunnen verwijzen dan anders in de accountlijst van de transactie zou passen | ProgramInstruction |
| ZK ElGamal Proof | ZkE1Gama1Proof11111111111111111111111111111 | Biedt zero-knowledge proof-verificatie voor ElGamal-versleutelde gegevens | — |
Is this page helpful?