Operar un nodo
xrs-node 0.1.1Rustpuertos 4000 · 56001 · 50008
Un binario, tres puertos, un archivo de claves.
Compilar
git clone https://github.com/ZZachWWins/xeriscointestnet && cd xeriscointestnet
cargo build --release
| Binario | Hace |
|---|---|
xrs-node | el nodo |
keypair_gen | escribe keypair.json |
wallet | construye transacciones, imprime el curl para enviarlas |
| Necesita | Por qué |
|---|---|
rustc | 1.94.1 en el último informe de remediación de Xeris; sin fijar |
cc, perl, make | OpenSSL vendored, SQLite bundled |
Claves
# keypair.json; --mainnet escribe keypair_mainnet.json
RUST_LOG=info ./target/release/keypair_gen
| Archivo | Contenido | Modo |
|---|---|---|
keypair.json | array JSON de 64 bytes, la clave secreta Ed25519 | 0600 |
dilithium3_sk.bin | clave secreta ML-DSA-65, 4,032 bytes; escrita en el primer arranque en el directorio de trabajo; autoverificada en cada arranque | 0600 |
dilithium3_pk.bin | clave pública, 1,952 bytes | umask |
keypair.json se carga con XerisKeypair.fromJsonFile.
Arrancar
| Flag | Por defecto | Significado |
|---|---|---|
--validator <seed-ip> <keypair.json> <data-dir> | — | unirse por un seed; si falta el keypair se genera |
--bootstrap <keypair.json> <data-dir> | — | primer nodo de una cadena; necesita la clave del tesoro |
--mainnet | off | chain id xeris-mainnet-v1; roster obligatorio; <seed-ip> ignorado |
--genesis | off | escribe un descriptor de génesis y sale |
--p2p-port | 4000 | P2P |
--rpc-port | 56001 | RPC |
--explorer-port | 50008 | API del explorador |
--genesis-pre-stake | — | obsoleto, ignorado |
RUST_LOG=info ./target/release/xrs-node \
--validator 138.197.116.81 keypair.json ./data
# mainnet: tres direcciones P2P
export XRS_FEDERATED_PRODUCERS='<pk1>@<ip1>:4000,<pk2>@<ip2>:4000,<pk3>@<ip3>:4000'
RUST_LOG=info ./target/release/xrs-node --mainnet \
--validator 138.197.116.81 keypair_mainnet.json ./data
Entorno
| Variable | Efecto |
|---|---|
XRS_FEDERATED_PRODUCERS | 3 entradas pubkey@ipv4:port, las direcciones P2P; obligatoria con --mainnet |
XRS_LOCAL_ONLY=1 | P2P y RPC escuchan en 127.0.0.1, sin seeds DNS; el explorador sigue en 0.0.0.0 |
XRS_SEED_PEERS | ip[:port] separados por comas, ≤ 200, de confianza; solo testnet |
XRS_MAX_DEEP_SYNC_BYTES | presupuesto de disco del deep-sync; por defecto 512 GiB, mínimo 1 GiB |
RUST_LOG | info muestra el banner y el log de bloques; sin definir solo imprime errores |
Puertos
| Puerto | Servicio | Protocolo | Escucha |
|---|---|---|---|
| 4000 | P2P | TCP, desafío-respuesta Ed25519 | 0.0.0.0, o 127.0.0.1 en modo local |
| 56001 | RPC | HTTP/1.1, sin TLS | 0.0.0.0, o 127.0.0.1 en modo local |
| 50008 | API del explorador | HTTP/1.1, sin TLS | 0.0.0.0 siempre |
Termina TLS en un proxy inverso. El limitador de escritura usa el peer TCP: un proxy, un presupuesto de 30 por minuto.
Archivos
| Ruta | Propósito |
|---|---|
<data-dir>/ledger.dat | bloques, una línea JSON cada uno, fsync antes de aplicar |
<data-dir>/tx_receipts.sqlite | historial del explorador, esquema 2; reconstruido por replay si la versión difiere; obligatorio en toda red |
<data-dir>/ledger.dat.recovered-txs.sqlite | diario de recuperación; creado en cada arranque |
<data-dir>/price_history_<pool>.json | ≤ 10,080 instantáneas por pool, una cada 100 bloques |
<data-dir>/ledger_snapshot.json, contract_state.json | se escriben, nunca se cargan |
<cwd>/dilithium3_*.bin | las claves PQ |
Dos nodos arrancados desde un mismo directorio de trabajo comparten una clave PQ.
Pares
| Fuente | Regla |
|---|---|
--validator <seed-ip> | se marca primero; puerto 4000 si no se indica |
XRS_SEED_PEERS | de confianza |
| lista de seeds DNS | una URL HTTPS leída al arrancar, 5 s de espera, salvo en modo local |
| lista integrada | vacía |
| mainnet | el roster sustituye a todas las fuentes anteriores |
| dirección | IPv4, puerto opcional; hostnames rechazados |
Stake y producción
| Paso | Acción |
|---|---|
| 1 | generar keypair.json |
| 2 | arrancar con --validator; el log dice needs 1000 to mine |
| 3 | fondear la dirección: ≥ 1,000 XRS más tarifas; sin faucet |
| 4 | wallet stake → POST /stake |
| 5 | wallet pq-register → POST /pq-register, antes del primer bloque |
# cada uno imprime el curl de envío; ejecútalo
./target/release/wallet stake keypair.json 1000
./target/release/wallet pq-register keypair.json
import { readFileSync } from 'node:fs';
import { XerisClient, XerisKeypair } from 'xeris-sdk';
const client = new XerisClient('http://127.0.0.1',
{ rpcPort: 56001, explorerPort: 50008 });
const kp = XerisKeypair.fromJsonFile('keypair.json');
const pk = readFileSync('dilithium3_pk.bin');
await client.stakeXrs(kp, 1000); // POST /stake
await client.pqKeyRegister(kp, pk, 'dilithium3', 3); // POST /pq-register
| Regla | Valor |
|---|---|
| producir bloques | stake ≥ 1,000 XRS; cuenta desde el bloque siguiente |
primer Stake | stake resultante ≥ 1,000 XRS; /stake no lo comprueba antes |
| recompensas de staking | stake ≥ 100 XRS; 7 % anual, cada 900 bloques, al saldo líquido |
| unstake | todo, o conservar ≥ 1,000 XRS; parcial ≥ 1 XRS, POST /unstake |
| unbonding | 151,200 slots (7 días); slasheable; se libera sin reclamar, GET /account/{address}/unstaking |
| atestaciones | stake ≥ 100 XRS; 0.01 XRS, una cada 10 bloques, dentro de 200 slots, hash de 32 bytes, ValidatorAttestation |
| slashing | 10 % del stake por doble firma probada; 5 % de eso al reportero, el resto se quema, SlashReport |
| clave PQ | una por nodo; los bloques la exigen desde el slot 2 |
mainnet Stake | solo claves del roster; el resto: Public self-staking is closed during federated beta |
Mainnet: la clave del nodo debe estar en el roster de 3 entradas
XRS_FEDERATED_PRODUCERS o el arranque falla.Estado
curl -s http://127.0.0.1:56001/health
curl -s http://127.0.0.1:50008/v2/stats
curl -s http://127.0.0.1:56001/stake/<address>
| Señal | Ruta | SDK |
|---|---|---|
| activo | GET /health | getHealth() |
| altura, TPS estimado | GET /v2/stats | getStats() |
stake, isValidator, blocksProposed | GET /stake/{address} | getStakeInfo(address) |
| clave PQ | GET /pq/keys/{address} | getPqKey(address) |
| recompensa por bloque, tarifas, halving | GET /network/economics | getNetworkEconomics() |
| pares | el log del nodo | — |
| métricas | ninguna | — |