Técnico › Claves y direcciones

Dirección

95 caracteres: un prefijo de red, dos claves públicas y un checksum en un Base58 especial

En resumen

Una dirección estándar de Monero = Base58( prefix ‖ B ‖ A ‖ checksum ). El prefijo indica la red y el tipo de dirección, B y A son las claves públicas de gasto y de visualización, y el checksum (suma de comprobación) son los primeros 4 bytes de Keccak-256 sobre todo lo anterior.

Estructura

12 B — clave pública de gasto A — clave pública de visual. control 1 byte 32 bytes 32 bytes 4 bytes 69 bytes → Base58 de Monero → 95 caracteres

Prefijo de red

El prefijo se escribe como varint (un byte para números pequeños). Por cómo funciona Base58, el prefijo determina el primer carácter de la dirección:

RedEstándarIntegradaSubdirección
mainnet18 → 4…19 → 4…42 → 8…
stagenet24 → 5…25 → 5…36 → 7…
testnet53 → 9…/A…54 → A…63 → B…

Checksum

checksum = Keccak256( prefix ‖ B ‖ A )[0..4]

Si la dirección tiene una errata, el checksum no coincidirá y el monedero se negará a enviar.

El Base58 de Monero no es el de Bitcoin

El mismo alfabeto (sin 0 O I l), pero otra codificación. Bitcoin convierte todo el mensaje en un único número grande y lo pasa a base 58. Monero corta los datos en bloques de 8 bytes y codifica cada bloque por separado en exactamente 11 caracteres (el último bloque incompleto, en menos, según la tabla).

bytes en el bloque12345678
caracteres2356791011

69 bytes = 8 bloques completos (88 caracteres) + 5 bytes (7 caracteres) = 95 caracteres. La ventaja: la longitud de la dirección siempre es la misma y la codificación es de tiempo lineal.

const ENC_BLOCK = [0, 2, 3, 5, 6, 7, 9, 10, 11];
function encodeBlock(block) {
  let n = 0n;
  for (const x of block) n = (n << 8n) | BigInt(x);       // big-endian dentro de un bloque
  let s = '';
  while (n > 0n) { s = ALPHABET[Number(n % 58n)] + s; n /= 58n; }
  return s.padStart(ENC_BLOCK[block.length], '1');
}

Dirección integrada

Una dirección integrada (prefijo 19) = una dirección estándar + un payment ID (identificador de pago) de 8 bytes (106 caracteres). El payment ID va cifrado dentro de la transacción y ayuda a una tienda a saber qué pedido se ha pagado. Hoy se recomiendan en su lugar las subdirecciones: una subdirección nueva por pedido.

Lo que la dirección no contiene

Lo importante: la dirección nunca se escribe en la blockchain. El remitente usa A y B para construir una dirección de un solo uso, y solo esta llega a la blockchain.