Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Guías de red y protocolo13 min de lectura

Leer hiperparámetros de subred de Bittensor por RPC

Una guía práctica para leer hiperparámetros de subred de Bittensor por Subtensor RPC, decodificar la estructura devuelta y almacenar valores en caché de forma segura.

TL;DR

Los hiperparámetros de subred de Bittensor son los parámetros que gobiernan el mecanismo de incentivos de una subred, incluyendo tempo, periodo de inmunidad, máximos validadores, dificultad, límite de tasa de pesos y configuración de registro. Son estado de la cadena, no constantes: la gobernanza y los propietarios de subred pueden cambiarlos en cualquier bloque, y difieren por subred, por lo que los clientes deben leerlos en lugar de codificarlos de forma fija. La ruta de lectura preferida es la API de runtime subnetInfo_getSubnetHyperparams, que devuelve una única estructura tipada compuesta de la misma manera que la compone el runtime. Las lecturas directas de almacenamiento de estado mediante state_getStorage son posibles pero requieren el hash exacto de la clave de almacenamiento y la decodificación SCALE, y las claves sin procesar son inestables entre actualizaciones del runtime. Esta guía muestra cómo leer, decodificar, verificar de forma cruzada y almacenar en caché los hiperparámetros correctamente, con ejemplos ejecutables de Node.js y una tabla de resultados para medir contra tu propio endpoint.

Qué es un hiperparámetro de subred de Bittensor

Un hiperparámetro de subred es uno de los parámetros que gobiernan el mecanismo de incentivos de una subred. El conjunto incluye tempo (el número de bloques en la época de una subred), periodo de inmunidad (cuánto tiempo una neurona recién registrada está protegida contra la desregistración), máximos validadores (el límite de permisos de validador), dificultad mínima y máxima, límite de tasa de pesos (con qué frecuencia se pueden establecer pesos) y configuración de registro, como el costo de registro y los bloques de registro permitidos. La documentación de Bittensor mantiene la referencia canónica en subnet hyperparameters.

Estos valores no son constantes en el protocolo. Son estado de la cadena: la gobernanza puede cambiarlos, y los propietarios de subred pueden ajustar parámetros específicos de la subred a través de las extrínsecas correspondientes. También difieren por subred, por lo que un valor leído para un netuid no te dice nada sobre otro. Un cliente que codifica de forma fija el tempo o los máximos validadores se desviará silenciosamente de la corrección la primera vez que cambie un parámetro.

Debido a que los hiperparámetros son estado, el comportamiento correcto del cliente es leerlos de la cadena en un bloque conocido y tratar cualquier copia en caché como válida solo para ese bloque. El resto de esta guía cubre las dos rutas de lectura, cómo decodificar el resultado y cómo mantener una caché honesta.

  • Tempo: bloques por época para el mecanismo de incentivos de la subred.
  • Periodo de inmunidad: bloques durante los cuales una neurona nueva está protegida contra la desregistración.
  • Máximos validadores: el límite de permisos de validador para la subred.
  • Dificultad mínima/máxima: límites de la dificultad de prueba de trabajo para el registro.
  • Límite de tasa de pesos: bloques mínimos entre operaciones de establecimiento de pesos.
  • Configuración de registro: costo y restricciones de registro relacionadas.

Por qué los hiperparámetros deben leerse, no codificarse de forma fija

Un cliente que asume un tempo fijo calculará mal los límites de época en el momento en que la gobernanza lo cambie. Un cliente que asume un máximo de validadores fijo reportará mal la capacidad de validadores. Lo mismo se aplica al periodo de inmunidad, los límites de dificultad y el límite de tasa de pesos. Cada uno de estos es un valor vivo que puede cambiar en cualquier bloque.

La consecuencia práctica es que cualquier cálculo posterior — sincronización de épocas, elegibilidad de validadores, estimación del costo de registro — debe derivarse de una lectura de hiperparámetros tomada en un bloque conocido, no de una constante en tu código fuente. Si necesitas contexto de época y emisión junto con los hiperparámetros, la guía Lecturas de tempo, épocas y emisión de subred de Bittensor cubre esas lecturas en detalle.

Leer en lugar de codificar de forma fija también hace que tu cliente sea resistente entre subredes. Una única ruta de código que lee hiperparámetros para un netuid dado funciona para todas las subredes, mientras que las constantes por subred multiplican el mantenimiento y la deriva.

La ruta de lectura de la API de runtime: subnetInfo_getSubnetHyperparams

La ruta de lectura preferida es la API de runtime subnetInfo_getSubnetHyperparams, que devuelve una única estructura tipada que contiene los hiperparámetros de la subred. Debido a que el runtime compone la estructura, los campos se ensamblan de la misma manera en que el propio runtime los usa, lo que elimina el riesgo de aplicar un hash incorrecto a una clave de almacenamiento o decodificar mal un valor SCALE.

Algunas versiones de subtensor exponen una variante V2 del método. El nombre y la versión del método difieren entre versiones de subtensor, así que trata el nombre exacto como documentado / varía según el nodo y confírmalo contra el nodo que estás consultando. La guía state_getMetadata y versiones de runtime de Substrate explica cómo inspeccionar los metadatos del runtime para descubrir qué métodos de la API de runtime expone un nodo.

Llama a la API de runtime en un bloque explícito cuando necesites reproducibilidad. Pasar un hash de bloque fija la lectura a ese estado, que es lo que deseas para el almacenamiento en caché y para la verificación cruzada contra una instantánea del metagrafo.

  • Devuelve una única estructura tipada en lugar de bytes de almacenamiento sin procesar.
  • La composición de campos coincide con el uso que hace el propio runtime.
  • El nombre y la versión del método varían según la versión de subtensor.
  • Fija a un hash de bloque para lecturas reproducibles.

La ruta de lectura directa de almacenamiento: state_getStorage

La alternativa es leer los mapas de almacenamiento de SubtensorModule directamente con state_getStorage. Esto requiere calcular la clave de almacenamiento correcta, que en Substrate se deriva del nombre del pallet, el nombre del elemento de almacenamiento y los argumentos de la clave, y luego se aplica hash con el hasher apropiado (twox o blake2, según el mapa). Equivocarse en cualquier parte de eso devuelve null o basura.

Incluso cuando la clave es correcta, el valor devuelto está codificado en SCALE y debe decodificarse según el tipo definido en los metadatos del runtime. Ese tipo puede cambiar entre actualizaciones del runtime, lo que hace que las claves de almacenamiento sin procesar y los decodificadores sean inestables con el tiempo. Por estas razones, la ruta de la API de runtime es preferible para la corrección, y las lecturas directas de almacenamiento se reservan mejor para casos en los que ninguna API de runtime expone el valor que necesitas.

Si lees el almacenamiento directamente, fija la lectura a un bloque y registra la versión del runtime junto con el valor, para que puedas detectar cuándo un decodificador necesita actualizarse.

  • Requiere el hash exacto de la clave de almacenamiento (twox/blake2) y decodificación SCALE.
  • El diseño de la clave y el tipo de valor pueden cambiar entre actualizaciones del runtime.
  • Devuelve null para una clave incorrecta o un valor ausente.
  • Prefiere la API de runtime cuando exista una.

Ensamblar un registro completo de subred con subnetInfo_getSubnetInfo

Los hiperparámetros son solo una parte del estado de una subred. Para ensamblar un registro completo de subred, combina los hiperparámetros con subnetInfo_getSubnetInfo, que devuelve el propietario, la emisión y el costo de registro, entre otros campos. Juntos te dan los parámetros que gobiernan el mecanismo más el contexto económico que lo rodea.

Para contexto de validadores y stake, la guía Estado de staking de Bittensor por RPC cubre las lecturas de delegación y stake, y Leer el estado del metagrafo de Bittensor cubre el metagrafo. Una vista completa de la subred normalmente une hiperparámetros, información de subred y una instantánea del metagrafo tomada en el mismo bloque.

Unir lecturas en el mismo bloque importa. Si lees los hiperparámetros en el bloque N y el metagrafo en el bloque N+1, un cambio de parámetro entre ambos puede hacer que los dos sean inconsistentes. Fija ambas lecturas al mismo hash de bloque.

Decodificar la estructura de hiperparámetros devuelta

La estructura devuelta por subnetInfo_getSubnetHyperparams contiene los campos que gobiernan la subred. Decodifica cada campo según su tipo: tempo y periodo de inmunidad son conteos de bloques, máximos validadores es un conteo, los límites de dificultad son numéricos y el límite de tasa de pesos es un intervalo de bloques. La configuración de registro suele ser numérica o booleana según el campo.

Algunos campos son específicos de la subred, por lo que un campo faltante no es necesariamente un error. Una subred puede no usar todos los parámetros, y una versión del runtime puede agregar o renombrar campos. Trata los campos ausentes como 'no aplicable o no expuesto por este nodo' en lugar de como un fallo de decodificación, y registra la versión del runtime junto con la estructura decodificada.

Debido a que la estructura está tipada, puedes decodificarla con los metadatos del runtime en lugar de crear un decodificador a mano. Esta es la principal ventaja de corrección de la ruta de la API de runtime sobre las lecturas de almacenamiento sin procesar.

  • Tempo y periodo de inmunidad: conteos de bloques.
  • Máximos validadores: conteo de permisos de validador.
  • Dificultad mínima/máxima: límites numéricos.
  • Límite de tasa de pesos: intervalo de bloques.
  • Los campos faltantes pueden ser específicos de la subred, no errores.

Ejemplo ejecutable de Node.js: leer hiperparámetros por WebSocket

El ejemplo a continuación se conecta a un endpoint WebSocket de Subtensor, llama a la API de runtime para los hiperparámetros de una subred, imprime los campos de la estructura y vuelve a leer después de un nuevo bloque. Reemplaza el endpoint y el netuid con tus propios valores. El endpoint es específico del proveedor; consulta la guía de RPC de Bittensor (RPC Assistant) para opciones de endpoint y la página de la red Bittensor Finney para contexto de red.

El script usa un cliente JSON-RPC 2.0 mínimo sobre WebSocket. Fija la lectura al último hash de bloque para que el valor sea reproducible, y se suscribe a nuevos bloques para activar una nueva lectura. Este es el patrón a usar en un servicio de larga duración.

const WebSocket = require('ws');

const ENDPOINT = 'wss://your-subtensor-endpoint';
const NETUID = 1;

let id = 0;
function call(ws, method, params) {
  return new Promise((resolve, reject) => {
    const reqId = ++id;
    const onMsg = (data) => {
      const msg = JSON.parse(data);
      if (msg.id !== reqId) return;
      ws.off('message', onMsg);
      if (msg.error) reject(new Error(JSON.stringify(msg.error)));
      else resolve(msg.result);
    };
    ws.on('message', onMsg);
    ws.send(JSON.stringify({ jsonrpc: '2.0', id: reqId, method, params }));
  });
}

async function readHyperparams(ws) {
  const hash = await call(ws, 'chain_getBlockHash', []);
  const params = await call(ws, 'state_call', [
    'SubnetInfoRuntimeApi_get_subnet_hyperparams',
    '0x' + NETUID.toString(16).padStart(8, '0'),
    hash
  ]);
  console.log('block', hash);
  console.log('hyperparams (SCALE hex)', params);
  return { hash, params };
}

(async () => {
  const ws = new WebSocket(ENDPOINT);
  await new Promise((r) => ws.on('open', r));
  await readHyperparams(ws);
  await call(ws, 'chain_subscribeNewHeads', []);
  ws.on('message', async (data) => {
    const msg = JSON.parse(data);
    if (msg.method === 'chain_newHead') {
      await readHyperparams(ws);
    }
  });
})();

Detectar una caché obsoleta y volver a leer según lo programado

Un valor de hiperparámetro en caché solo es válido para el bloque en el que se leyó. Para detectar obsolescencia, almacena el hash de bloque y la versión del runtime junto con el valor, y vuelve a leer según una programación o ante una suscripción de nuevo bloque. Si la versión del runtime cambia, invalida la caché y vuelve a decodificar.

Un patrón práctico es volver a leer los hiperparámetros cada N bloques (donde N es pequeño en relación con el tempo) y forzar una nueva lectura siempre que cambie la versión del runtime. Para una subred con un tempo corto, es apropiado un intervalo de nueva lectura más corto; para un tempo largo, un intervalo más largo está bien. La clave es acotar la obsolescencia máxima en lugar de asumir que el valor nunca cambia.

Si sirves hiperparámetros a otros servicios, expón el hash de bloque con el valor para que los consumidores puedan decidir si el valor es lo suficientemente reciente para su caso de uso.

  • Almacena el hash de bloque y la versión del runtime con el valor.
  • Vuelve a leer según una programación o ante una suscripción de nuevo bloque.
  • Invalida la caché cuando cambie la versión del runtime.
  • Expón el hash de bloque a los consumidores posteriores.

Verificar de forma cruzada los hiperparámetros contra el metagrafo

Una verificación cruzada útil es comprobar que el número de validadores activos en el metagrafo respeta max_validators. Lee el metagrafo en el mismo bloque que los hiperparámetros y cuenta los permisos de validador. Si el conteo supera max_validators, o tu lectura está obsoleta o estás contando el campo incorrecto.

El mismo enfoque se aplica al periodo de inmunidad: una neurona registrada dentro de la ventana de inmunidad no debería ser desregistrada. La verificación cruzada contra el metagrafo detecta errores de decodificación y cachés obsoletas que una sola lectura pasaría por alto. La guía Leer el estado del metagrafo de Bittensor cubre los campos del metagrafo que necesitas.

Las verificaciones cruzadas no sustituyen una decodificación correcta, pero son una forma barata de detectar deriva en un servicio en ejecución.

Tabla de resultados: medir contra tu propio endpoint

Debido a que el comportamiento del endpoint y las versiones del runtime varían, mide contra tu propio endpoint en lugar de confiar en números publicados. La tabla a continuación es una plantilla para completar con tus propias observaciones. Registra el endpoint, el hash de bloque, la versión del runtime y los campos decodificados para cada lectura.

Ejecuta la lectura en varios bloques y compara. Si un campo cambia sin un cambio de versión del runtime, eso es un cambio de gobernanza o del propietario de la subred y tu caché debería haberlo detectado. Si un campo no se decodifica, registra la versión del runtime y verifica los metadatos para el tipo actual.

  • Endpoint: tu URL WebSocket o HTTP de Subtensor.
  • Hash de bloque: el bloque al que se fijó la lectura.
  • Versión del runtime: de state_getRuntimeVersion.
  • Tempo, periodo de inmunidad, máximos validadores: valores decodificados.
  • Límite de tasa de pesos, dificultad mínima/máxima: valores decodificados.
  • Verificación cruzada: validadores activos vs máximos validadores.

Limitaciones, compensaciones y solución de problemas

Los hiperparámetros son estado de la cadena que la gobernanza y los propietarios de subred pueden cambiar en cualquier bloque. El nombre y la versión del método de la API de runtime difieren entre versiones de subtensor, así que trata el nombre exacto como documentado / varía según el nodo y confírmalo contra tu endpoint. Las claves de almacenamiento sin procesar son inestables entre actualizaciones del runtime, y algunos campos son específicos de la subred, por lo que un campo faltante no es necesariamente un error.

Modos de fallo comunes: un resultado null de state_getStorage generalmente significa una clave de almacenamiento incorrecta o un valor ausente; un fallo de decodificación generalmente significa que el tipo del runtime cambió; un valor obsoleto generalmente significa que la caché no se invalidó ante un cambio de versión del runtime. Para problemas de endpoint y conectividad, consulta la guía de RPC de Bittensor (RPC Assistant).

Para servicios en producción, prefiere la ruta de la API de runtime, fija las lecturas a un bloque, almacena la versión del runtime y verifica de forma cruzada contra el metagrafo. Si necesitas endpoints gestionados, las páginas del servicio de API y precios de RPC describen las opciones, y el centro de aprendizaje de OnFinality recopila guías relacionadas.

  • El nombre/versión del método varía según el nodo: confírmalo contra los metadatos.
  • Las claves de almacenamiento sin procesar son inestables entre actualizaciones del runtime.
  • Los campos faltantes pueden ser específicos de la subred, no errores.
  • Resultado de almacenamiento null: clave incorrecta o valor ausente.
  • Fallo de decodificación: el tipo del runtime cambió.
  • Valor obsoleto: caché no invalidada ante un cambio de versión.

Próximos pasos para construir un cliente consciente de los hiperparámetros

Comienza leyendo los hiperparámetros de un único netuid en un bloque fijado, luego decodifica la estructura usando los metadatos del runtime. Agrega una suscripción de nuevo bloque y vuelve a leer en un intervalo acotado. Almacena el hash de bloque y la versión del runtime con cada valor, y expónlos a los consumidores.

Una vez que la ruta de lectura sea estable, únela con subnetInfo_getSubnetInfo y una instantánea del metagrafo en el mismo bloque para ensamblar un registro completo de subred. Usa las verificaciones cruzadas descritas anteriormente para detectar deriva. Para lecturas relacionadas, consulta las guías Lecturas de tempo, épocas y emisión de subred de Bittensor y Estado de staking de Bittensor por RPC.

Finalmente, trata la lectura de hiperparámetros como un contrato versionado: cuando cambie la versión del runtime, vuelve a verificar tu decodificador y tu lógica de invalidación de caché. Esa disciplina es lo que mantiene correcto a un cliente a medida que la red evoluciona.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar