Programas

En Solana, los "contratos inteligentes" se llaman programas. Los programas se despliegan en la cadena en cuentas que contienen el binario ejecutable compilado del programa. Los usuarios interactúan con los programas enviando transacciones que contienen instrucciones que indican al programa qué hacer.

Puntos clave

  • Los programas son cuentas que contienen código ejecutable, organizado en funciones llamadas instrucciones.
  • Aunque los programas son sin estado, pueden incluir instrucciones que crean y actualizan otras cuentas para almacenar datos.
  • Una autoridad de actualización puede actualizar los programas. Una vez que esta autoridad se elimina, el programa se vuelve inmutable.
  • Los usuarios pueden verificar que los datos de una cuenta de programa en la cadena coinciden con su código fuente público mediante compilaciones verificables.

Escribiendo programas en Solana

Los programas de Solana se escriben predominantemente en el lenguaje de programación Rust, con dos enfoques comunes para el desarrollo:

  • Anchor: Un framework diseñado para el desarrollo de programas en Solana. Proporciona una forma más rápida y sencilla de escribir programas, utilizando macros de Rust para reducir el código repetitivo. Para principiantes, se recomienda comenzar con el framework Anchor.

  • Rust nativo: Este enfoque implica escribir programas de Solana en Rust sin utilizar ningún framework. Ofrece más flexibilidad pero conlleva una mayor complejidad.

Actualizando programas de Solana

Para obtener más información sobre el despliegue y la actualización de programas, consulta la página de despliegue de programas.

Los programas pueden ser modificados directamente por una cuenta designada como "autoridad de actualización", que normalmente es la cuenta que desplegó originalmente el programa. Si la autoridad de actualización es revocada y establecida como None, el programa se vuelve inmutable y ya no puede ser actualizado.

Programas verificables

Las compilaciones verificables permiten a cualquier persona comprobar si el código en cadena de un programa coincide con su código fuente público, haciendo posible detectar discrepancias entre la versión fuente y la implementada.

La comunidad de desarrolladores de Solana ha introducido herramientas para soportar compilaciones verificables, permitiendo tanto a desarrolladores como a usuarios verificar que los programas en cadena reflejan con precisión su código fuente compartido públicamente.

  • Búsqueda de programas verificados: Para comprobar rápidamente los programas verificados, los usuarios pueden buscar una dirección de programa en Solana Explorer. Ver un ejemplo de un programa verificado aquí.

  • Herramientas de verificación: La CLI de compilación verificable de Solana de Ellipsis Labs permite a los usuarios verificar independientemente los programas en cadena contra el código fuente publicado.

  • Soporte para compilaciones verificables en Anchor: Anchor proporciona soporte integrado para compilaciones verificables. Los detalles se pueden encontrar en la documentación de Anchor.

Berkeley Packet Filter (BPF)

Solana utiliza LLVM (Low Level Virtual Machine) para compilar programas en archivos ELF (Executable and Linkable Format). Estos archivos contienen la versión personalizada de Solana del bytecode eBPF, llamado "Solana Bytecode Format" (sBPF). El archivo ELF contiene el binario del programa y se almacena en cadena en una cuenta ejecutable cuando el programa se implementa.

Programas integrados

Programas cargadores

Cada programa en sí es propiedad de otro programa, que es su cargador. Actualmente, existen cinco programas cargadores:

CargadorID del programaNotasEnlace a instrucciones
nativeNativeLoader1111111111111111111111111111111Es propietario de los otros cuatro cargadores
v1BPFLoader1111111111111111111111111111111111Las instrucciones de gestión están deshabilitadas, pero los programas aún se ejecutan
v2BPFLoader2111111111111111111111111111111111Las instrucciones de gestión están deshabilitadas, pero los programas aún se ejecutanInstrucciones
v3BPFLoaderUpgradeab1e11111111111111111111111Está siendo eliminado gradualmenteInstrucciones
v4LoaderV411111111111111111111111111111111111Se espera que v4 se convierta en el cargador estándarInstrucciones

Estos cargadores son necesarios para crear y gestionar programas personalizados:

  • Desplegar un nuevo programa o buffer
  • Cerrar un programa o buffer
  • Redesplegar / actualizar un programa existente
  • Transferir la autoridad sobre un programa
  • Finalizar un programa

Loader-v3 y loader-v4 admiten modificaciones a los programas después de su despliegue inicial. El permiso para hacerlo está regulado por la autoridad de un programa porque la propiedad de la cuenta de cada programa reside en el cargador.

Programas precompilados

Programa Ed25519

ProgramaID del programaDescripciónInstrucciones
Programa Ed25519Ed25519SigVerify111111111111111111111111111Verifica firmas ed25519. Si alguna firma falla, se devuelve un error.Instrucciones

El programa ed25519 procesa una instrucción. El primer u8 es un contador del número de firmas a verificar, seguido de un byte de relleno. Después de eso, se serializa la siguiente estructura, una por cada firma a verificar.

Ed25519SignatureOffsets
struct Ed25519SignatureOffsets {
signature_offset: u16, // offset to ed25519 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to public key of 32 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}

El pseudocódigo de la verificación de firma:

process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
instruction_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
}

Programa Secp256k1

ProgramaID del programaDescripciónInstrucciones
Programa Secp256k1KeccakSecp256k11111111111111111111111111111Verifica operaciones de recuperación de clave pública secp256k1 (ecrecover).Instrucciones

El programa secp256k1 procesa una instrucción que toma como primer byte un contador de la siguiente estructura serializada en los datos de instrucción:

Secp256k1SignatureOffsets
struct Secp256k1SignatureOffsets {
secp_signature_offset: u16, // offset to [signature,recovery_id] of 64+1 bytes
secp_signature_instruction_index: u8, // instruction index to find signature
secp_pubkey_offset: u16, // offset to ethereum_address pubkey of 20 bytes
secp_pubkey_instruction_index: u8, // instruction index to find pubkey
secp_message_data_offset: u16, // offset to start of message data
secp_message_data_size: u16, // size of message data
secp_message_instruction_index: u8, // instruction index to find message data
}

El pseudocódigo de la verificación de recuperación:

process_instruction() {
for i in 0..count {
// i'th index values referenced:
instructions = &transaction.message().instructions
signature = 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
}

Esto permite al usuario especificar cualquier dato de instrucción en la transacción para los datos de firma y mensaje. Al especificar una sysvar de instrucciones especial, también se pueden recibir datos de la transacción misma.

El costo de la transacción contará el número de firmas a verificar multiplicado por el multiplicador de costo de verificación de firma.

Programa Secp256r1

ProgramaID del programaDescripciónInstrucciones
Programa Secp256r1Secp256r1SigVerify1111111111111111111111111Verifica hasta 8 firmas secp256r1. Toma una firma, clave pública y mensaje. Devuelve error si alguna falla.Instrucciones

El programa secp256r1 procesa una instrucción. El primer u8 es un contador del número de firmas a verificar, seguido de un byte de relleno. Después de eso, la siguiente estructura se serializa, una por cada firma a verificar:

Secp256r1SignatureOffsets
struct Secp256r1SignatureOffsets {
signature_offset: u16, // offset to compact secp256r1 signature of 64 bytes
signature_instruction_index: u16, // instruction index to find signature
public_key_offset: u16, // offset to compressed public key of 33 bytes
public_key_instruction_index: u16, // instruction index to find public key
message_data_offset: u16, // offset to start of message data
message_data_size: u16, // size of message data
message_instruction_index: u16, // index of instruction data to get message data
}

El pseudocódigo de la verificación de firma:

process_instruction() {
if data.len() < SIGNATURE_OFFSETS_START {
return Error
}
num_signatures = data[0] as usize
if num_signatures == 0 || num_signatures > 8 {
return Error
}
expected_data_size = num_signatures * SIGNATURE_OFFSETS_SERIALIZED_SIZE + SIGNATURE_OFFSETS_START
if 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
}

Nota: Se imponen valores S bajos para todas las firmas para evitar la maleabilidad accidental de la firma.

Programas principales

El génesis del clúster de Solana incluye una lista de programas especiales que proporcionan funcionalidades básicas para la red. Históricamente se les conocía como programas "nativos" y solían distribuirse junto con el código del validator.

ProgramaID del programaDescripciónInstrucciones
System Program11111111111111111111111111111111Crea nuevas cuentas, asigna datos de cuenta, asigna cuentas a programas propietarios, transfiere lamports desde cuentas propiedad del System Program y paga tarifas de transacción.SystemInstruction
Programa de VotaciónVote111111111111111111111111111111111111111Crea y gestiona cuentas que rastrean el estado de votación del validator y las recompensas.VoteInstruction
Programa de StakeStake11111111111111111111111111111111111111Crea y gestiona cuentas que representan stake y recompensas para delegaciones a validators.StakeInstruction
Programa de ConfiguraciónConfig1111111111111111111111111111111111111Añade datos de configuración a la cadena, seguidos por la lista de claves públicas que pueden modificarla. A diferencia de otros programas, el programa de Configuración no define instrucciones individuales. Tiene solo una instrucción implícita: "almacenar". Sus datos de instrucción son un conjunto de claves que controlan el acceso a la cuenta y los datos a almacenar en ella.ConfigInstruction
Programa de Presupuesto de CómputoComputeBudget111111111111111111111111111111Establece límites y precios de unidades de cómputo para transacciones, permitiendo a los usuarios controlar recursos de cómputo y tarifas de priorización.ComputeBudgetInstruction
Programa de Tabla de Búsqueda de DireccionesAddressLookupTab1e1111111111111111111111111Gestiona tablas de búsqueda de direcciones, que permiten a las transacciones hacer referencia a más cuentas de las que cabrían en la lista de cuentas de la transacción.ProgramInstruction
Programa de Prueba ZK ElGamalZkE1Gama1Proof11111111111111111111111111111Proporciona verificación de pruebas de conocimiento cero para datos cifrados con ElGamal.

Is this page helpful?

Tabla de Contenidos

Editar Página