Rand Protocol
Documentación
Conceptos fundamentales

Transacciones y acciones

La transacción en la red, su id, cada Action que conoce el libro mayor, cuáles admite chain 20 y el orden en que un nodo comprueba un envío.

Use esta página para construir, enviar o decodificar una transacción: la forma de transmisión que toma rand_sendTransaction, cómo se calcula el id, la lista completa de acciones con sus reglas de paquete y de comisión, y el orden de admisión que decide qué error se recibe primero.

La transacción

Transaction { chain_id: u64, bundle: Option<Bundle>, action: Action }

Bundle {                                        // the hidden-asset bundle (since chain 14)
  anchor: Word8, nullifiers: [Word8; 4], commitments: [Word8; 4],
  fee: u64, burn_a: u64, burn_r: u64, burn_asset: u32, time: u32,
  envelopes: [Envelope; 4], proof: Vec<u8>,     // postcard(Proof) of the hidden-asset guest
  auth_commit: Word8, auth_proof: Vec<u8>,      // since chain 17: split authorisation's c and its auth proof
}
Envelope { kem_ct: Vec<u8>, to_receiver: Vec<u8>, to_sender: Vec<u8>, body: Vec<u8> }

Word8 son ocho palabras u32 little-endian, representadas como 64 caracteres hexadecimales en minúscula. La forma de transmisión es bincode(Transaction) con los valores por defecto de bincode (enteros de ancho fijo, prefijos de longitud de 8 bytes, etiquetas de enumeración u32), y rand_sendTransaction la recibe en hexadecimal. No hay firma sobre la transacción ni campo de remitente: un paquete se autoriza por sus pruebas (la prueba del paquete y, desde la cadena 17, la prueba de autorización que la acompaña), y una acción firmada lleva la firma dentro de sí misma. La protección contra repetición es el conjunto de anuladores para los paquetes, un nonce por validador en el registro para las acciones de staking firmadas, un mint_nonce por token para TokenMint y SetAuthority, y el pause_nonce y el list_nonce del puente para sus acciones de gobernanza.

Una transacción lleva como máximo un paquete, y toda acción que no sea independiente de paquete lleva exactamente uno. Las ranuras 0–1 del paquete llevan un activo privado y las ranuras 2–3 llevan RAND, de modo que una sola prueba mueve un token y paga su comisión en RAND; la quema del puente con dos paquetes del diseño anterior ya no existe: una quema es un solo paquete (Notas).

La wallet rand construye todo esto mediante randprotocol_client::wallet::{send, submit}: selecciona las entradas, obtiene el ancla, calcula los testigos a partir de la copia propia del árbol de la wallet, construye las salidas y sella los cuatro sobres, toma la vinculación de la transacción, genera la prueba del paquete y la prueba de autorización, comprueba el digest publicado de la prueba del paquete y envía.

La vinculación de la transacción

Una transacción no tiene firma, y la prueba de un paquete solo se compromete con el digest del propio paquete: ancla, anuladores, compromisos, comisión, los campos de quema, time. Hasta la cadena 13 nada ataba un paquete probado a la acción con la que viajaba ni a sus sobres, de modo que cualquiera que viera una transacción podía conservar todos los bytes de la prueba y cambiar el resto: el destino de un BridgeBurn, el validador de un Bond, un sobre. Desde la cadena 14, toda prueba de paquete se genera sobre la vinculación de la transacción y se verifica contra ella:

binding(tx) = blake3("rand-tx-bind-1" || bincode(chain_id, bundle', action'))            chains 14 to 19
binding(tx) = blake3("rand-tx-bind-2" || bincode(genesis_hash, chain_id, bundle', action'))  chain 20
                                                                                  as 8 LE u32 words

donde ' significa que cada cadena de bytes de prueba de un paquete se sustituye por el vector vacío: bundle.proof, desde la cadena 17 bundle.auth_proof, y el proof de un Aggregate. Todo lo demás queda dentro: auth_commit, los cuatro sobres, todos los campos de quema, un destino, un validador, un destinatario, las firmas, la atestación del guardián y sus cofirmas Dilithium2, y la prueba propia de un Call. Las ocho palabras viajan en el segmento de entrada pública de la prueba, cuyo digest H_PUB el circuito ya vincula, de modo que la corrección no requirió cambios en el programa invitado ni en el circuito; el nodo ejecuta Machine::verify_public(hc_bundle, binding, proof) y rechaza una prueba de paquete que declare cualquier otra altura pública (public height not the transaction binding's). Transaction::binding es la única función que la wallet llama antes de probar y el ledger antes de verificar. Desde la cadena 17, la prueba de autorización se genera sobre las mismas ocho palabras y se verifica contra ellas, por lo que tampoco puede trasladarse a otra transacción.

La cadena 20 vincula el hash de génesis. Hasta la cadena 19, la vinculación y los mensajes firmados de las acciones independientes de paquete cubrían solo el id de cadena, de modo que dos cadenas con el mismo id de cadena (una recompilación, una copia privada) habrían aceptado mutuamente sus pruebas y firmas. El génesis de la cadena 20 establece binding_domain: 1 (v0.6.8, auditoría v6 BIND-1; crates/randprotocol-core/src/types/binding.rs). El hash de génesis encabeza entonces cada preimagen bajo una etiqueta una versión más alta: rand-tx-bind-2 y rand-call-bind-2 para las dos vinculaciones, y lo mismo para el mint del faucet (rand-mint-3), Unbond y Withdraw (rand-unbond-2, rand-withdraw-2), los mensajes de mint y de autoridad de RPL (rand-rpl-mint-2, rand-rpl-authority-2), las acciones de agregador y los mensajes de gobernanza del puente. En una cadena así, el registro de un validador es siempre el mensaje v2 (génesis, cadena, dirección, pago). Nada probado o firmado para una cadena se verifica en otra, sea cual sea su id de cadena. Las palabras de la vinculación son una entrada pública, por lo que no cambió ningún programa invitado ni clave del verificador. Una wallet anterior a v0.6.8 sigue probando contra la forma con id de cadena y es rechazada en la cadena 20. rand_getLimits y rand_status sirven binding_domain (1 en la cadena 20, 0 sin el campo).

Bajo el génesis hardening_v6 (cadenas 16 a 20), la prueba propia de un Call también queda vinculada, mediante un segundo digest de la misma construcción bajo su propio dominio, con la prueba de la llamada en blanco además de las pruebas del paquete:

call_binding(tx) = blake3("rand-call-bind-1" || bincode(chain_id, bundle', action''))   as 8 LE u32 words

En la cadena 20 la etiqueta es rand-call-bind-2 y el hash de génesis encabeza la preimagen, como antes. La prueba de un Invoke se vincula del mismo modo, conservando en la preimagen su transición declarada, de manera que la prueba se compromete exactamente con el cambio de estado, los pagos y los destinatarios que lleva la transacción.

La prueba de la llamada lleva estas palabras en su segmento de entrada pública, después de la entrada pública de despliegue del programa cuando la tiene, por lo que una copia de ella adjunta a otro paquete de comisión no se verifica. Las dos vinculaciones se anidan: la wallet elige las notas del paquete de comisión y construye la transacción con las pruebas vacías, prueba la llamada contra la vinculación de la llamada, incorpora esa prueba y solo entonces toma la vinculación de la transacción y prueba el paquete.

La consecuencia para un cliente: construya la transacción completa (salidas, sobres, acción) antes de probar. Una wallet construida antes de la bifurcación prueba contra el segmento público vacío y es rechazada. Las acciones independientes de paquete no tienen prueba que vincular y descansan en sus propias firmas. La vinculación no es el id de la transacción, que no cambia.

El id de la transacción

txid = blake3("rand-txid-3" || bincode(view))

donde view es la transacción con los bytes proof del paquete sustituidos por blake3(proof) (proof_hash) y sus bytes auth_proof por blake3(auth_proof) (auth_proof_hash, después de auth_commit, que entra tal cual), con todos los demás campos sin cambios. El dominio fue rand-txid-2, sin los dos campos de autorización, hasta la cadena 16; todos los ids de transacción cambiaron con la cadena 17. Hashear la prueba por su digest es lo que permite que un paquete podado (agregación de bloques, no activa en la cadena 20) conserve el mismo id que su forma completa; un paquete podado conserva su prueba de autorización. Una transacción independiente de paquete hashea sus bytes tal como están. El mismo id sirve de clave para el mempool, los recibos y toda consulta RPC.

Todas las acciones

Action es una enumeración de bincode, con etiquetas en el orden de declaración:

tagaccióncamposbundletarifa mínima
0None—obligatorioBUNDLE_BASE = 0.001 RAND
1Mintcm, pk, time, r, envelope, amount, minter: PublicKey, signaturedebe estar ausente0 (firmado por el validador; solo en cadenas con faucet, amount ≤ 100 RAND)
2Deploybase_pc: u32, words: Vec<u32>, public: Vec<u32>obligatoriobase + 100,000 unidades por cada palabra de programa y palabra pública
3Callprogram, proof, input_envelope: Option<CallEnvelope>obligatorioen la cadena 20, base + gas_price × el GAS_LIMIT declarado en la prueba + byte_price por KiB de prueba y de envelope de entrada; base + call_fee(tier) en una cadena sin sección gas
4Bondvalidator, amount, registration: Option<Registration>obligatorio, y burn_r == amountbase
5Unbondvalidator, amount, nonce, signaturedebe estar ausente0
6Withdrawvalidator, amount, nonce, time, r, envelope, signaturedebe estar ausente0 en la transmisión; la base se descuenta de amount
7BridgeAttestattestation, recipient: ShieldedAddress, r, time, asset, envelope, pq_signatures: Vec<PqSignature>obligatoriobase
8BridgeBurnasset, amount, relayer_fee, to_chain: u16, token: [u8; 32], to: [u8; 32]obligatorio, con burn_asset == asset y burn_a == amountBRIDGE_BURN_FEE = 0.01 RAND
9RegisterAggregatorregistrationobligatorio, burn_r = la fianzabase
10UnbondAggregatoraggregator, nonce, signaturedebe estar ausente0
11WithdrawAggregatoraggregator, nonce, time, r, envelope, signaturedebe estar ausente0
12SlashAggregatordos cabeceras de agregado firmadasdebe estar ausente0
13Aggregatecovers, proof, aggregator, nonce, time, r, envelope, signaturedebe estar ausente0
14RegisterTokenname, symbol, decimals: u8, authority: MintAuthority, initial: Option<InitialMint>, salt: [u8; 32], index: u32obligatoriobase + la registration_fee del registro (1 RAND en la cadena 20, quemado)
15TokenMintasset, amount, recipient: ShieldedAddress, r, time, envelope, nonce, signatureobligatoriobase
16SetAuthorityasset, new: Option<PublicKey>, nonce, signatureobligatoriobase
17TokenBurnasset, amountobligatorio, con burn_asset == asset y burn_a == amountbase
18PauseMintsnonce, signaturedebe estar ausente0
19UnpauseMintsnonce, pq_signaturesdebe estar ausente0
20RegisterBridgedTokenname, symbol, salt, chain: u16, token: [u8; 32], decimals: u8, nonce, pq_signaturesobligatoriobase + registration_fee
21ListBackingtoken_index, chain: u16, token: [u8; 32], decimals: u8, nonce, pq_signaturesobligatoriobase
22RotatePqGuardiansnew_pq_guardians: Vec<PublicKey>, nonce, pq_signaturesdebe estar ausente0
23RotatePauseKeynew_pause_key: PublicKey, nonce, pq_signaturesdebe estar ausente0
24ClaimVestedentry: [u8; 32], amount, nonce, to: ShieldedAddress, time, r, envelope, signaturedebe estar ausente0 en la transmisión; la base se descuenta de amount
25RevokeVestingentry: [u8; 32], unvested, nonce, to: ShieldedAddress, time, r, envelope, signatures (desde v0.6.8, un umbral de los revocadores de la entrada, que paga a la tesorería que nombra su entrada de génesis; antes, una sola signature)debe estar ausente0 en la transmisión; la base se descuenta de unvested
26BondVestedentry: [u8; 32], validator, amount, registration: Option<Registration>, nonce, signaturedebe estar ausente0
27UnbondVestedentry: [u8; 32], amount, nonce, signaturedebe estar ausente0
28AdmitValidatorcandidate: PublicKey, signatures: Vec<(PublicKey, Signature)>debe estar ausente0
29SlashEquivocationfirst, second: dos cabeceras de bloque firmadas por un mismo líder para una misma vistadebe estar ausente0
30RotatePqGuardiansV2new_pq_guardians: Vec<PublicKey>, possession: Vec<Vec<u8>>, nonce, pq_signaturesdebe estar ausente0
31RotatePauseKeyV2new_pause_key: PublicKey, possession: Vec<u8>, nonce, pq_signaturesdebe estar ausente0
32CancelRotationkind: u8, nonce, signaturedebe estar ausente0
33Invokeprogram, proof, input_envelope: Option<CallEnvelope>, transition: Transitionobligatorio; burn_r y burn_a de burn_asset son lo que entra en el programael mínimo de una llamada + cell_fee por cada celda creada
MintAuthority = None | Key(PublicKey) | Bridge { backings: Vec<Backing> } | Program(Hash)
InitialMint   { amount: u64, recipient: ShieldedAddress, r: Word8, time: u32, envelope: Envelope }
PqSignature   { index: u8, signature: Vec<u8> }   // one guardian's Dilithium2 co-signature, by set index

En la cadena 20 se pueden usar las etiquetas 0 a 8, 14 a 21, 28 y 30 a 33. Su génesis tiene una sección bridge con rules_v2, una sección tokens, staking.admission_by_vote (etiqueta 28), bridge.rotation (etiquetas 30 a 32) y program_state (etiqueta 33). Las etiquetas 22 y 23 se rechazan allí: con bridge.rotation.needs_possession, una rotación debe ser la forma …V2, que lleva la firma propia de cada clave nueva. En la cadena 19, que no tenía ninguna de esas secciones, se podían usar las etiquetas 0 a 8 y 14 a 23 (la cadena 14, sin rules_v2, rechazaba la 22 y la 23). SlashEquivocation necesita una sección staking.slashing, y la de la cadena 20 es nula. Las cinco acciones de agregación necesitan una sección aggregation, que la cadena 20 no tiene (una compilación se niega a arrancar con un génesis que la incluya hasta que la agregación se vuelva a medir). Un nodo rechaza todas estas acciones en la puerta de entrada, antes de cualquier otra comprobación, pero siguen ocupando sus etiquetas bincode, de modo que un codificador que fije los números de etiqueta en el código debe contarlas. La agregación se documenta como próxima en Proofs. Las cuatro acciones de vesting de génesis (etiquetas 24 a 27, en la compilación desde v0.5.11) necesitan una sección vesting, que ninguna cadena ha tenido, la cadena 20 incluida, y se rechazan en la admisión si falta. Las etiquetas 28 a 33 son nuevas en v0.6.8 y se añaden al final, de modo que el historial de todas las cadenas anteriores se sigue decodificando.

Las cuatro acciones de RPL (etiquetas 14 a 17) registran un token, emiten más unidades de uno autorizado por Key, ceden o renuncian a su autoridad de emisión, y queman una tenencia; un RegisterToken que nombre una autoridad Bridge o Program se rechaza. No existe una acción de transferencia de tokens: una transferencia de tokens es un None, indistinguible de un pago en RAND. Véase RPL tokens. Las cuatro acciones de gobernanza del puente (etiquetas 18 a 21) son la pausa de emisión, su levantamiento y el listado de un token puenteado o de un respaldo adicional tras el génesis. PauseMints la firma la clave de pausa del génesis, que solo puede pausar; las otras tres requieren un quórum de los guardianes Dilithium2 (PQ). Un BridgeAttest también lleva un quórum de este tipo, junto al ECDSA. Las etiquetas 22 y 23, bajo rules_v2 del puente, sustituyen el conjunto de guardianes PQ o la clave de pausa, cada una bajo un quórum PQ del conjunto vigente y el rotation_nonce del puente. Las etiquetas 30 y 31 hacen lo mismo bajo bridge.rotation y además llevan la firma Dilithium2 propia de cada clave nueva sobre el mensaje de rotación, una prueba de que la clave está en poder de quien la presenta; en la cadena 20 una rotación se registra como pendiente y entra en vigor tras delay_secs, 86,400 s. CancelRotation (etiqueta 32), firmada por la clave de pausa vigente, descarta una rotación pendiente antes de que entre en vigor. Véase Bridge.

AdmitValidator (etiqueta 28) es el voto del conjunto de validadores para admitir una clave nueva: firmas de validadores que posean más de dos tercios del stake, en orden ascendente de dirección. Con staking.admission_by_vote (cadena 20), un Bond que registraría a un validador nuevo se rechaza salvo que su dirección haya sido admitida de este modo (Staking). Invoke (etiqueta 33, RPL-2) es una llamada cuya prueba avala una transition declarada del estado del programa: las celdas leídas y escritas, lo que los campos de quema del bundle aportan a la bóveda del programa, y las notas que la bóveda paga o que el programa emite. El ledger aplica la transición si cada lectura declarada sigue vigente y ambas pruebas se verifican (Programs).

Un Deploy y un Call son transacciones blindadas ordinarias cuyo bundle es una autotransferencia de cero: existe para pagar el mínimo con las propias notas del llamante, de modo que la cadena nunca sabe de quién eran. RAND sale del pool solo mediante burn_r — el stake de un Bond, la fianza de un RegisterAggregator, el depósito de un Invoke en la bóveda de un programa — y un token solo mediante burn_a, con burn_asset que lo nombre, en un TokenBurn, un BridgeBurn o un Invoke. Toda otra acción no quema nada, y un bundle con burn_asset = 0 y burn_a distinto de cero se rechaza en todas partes.

Orden de admisión

Ledger::validate_inner comprueba lo barato antes que lo costoso, en este orden; la mempool ejecuta la misma comprobación antes de difundir, de modo que una transacción defectuosa se rechaza una sola vez, en el borde.

  1. Límites de tamaño: la transacción completa ≤ max_block_bytes de la cadena; cada uno de los cuatro sobres del paquete, y cualquier sobre de nota que lleve la acción, exactamente el envelope_bytes del génesis (1.860 en la chain 20; como máximo 2.048 bytes en una cadena sin ese campo); la prueba del paquete, la prueba de autorización y la prueba de una llamada, cada una ≤ max_proof_bytes (2 MiB por defecto, 4 MiB en el génesis de la chain 20; eran 8 MiB en las chains 13 a 16); un programa ≤ el límite de programa de la cadena (4.096 palabras por defecto, 65.535 en el génesis de la chain 20); un sobre de llamada ≤ max_call_envelope_bytes (18.432 bytes por defecto, 65.536 en la chain 20); una atestación ≤ 16 KiB. Una prueba de paquete en la forma de marcador sellada (podada) se rechaza aquí fuera de la sincronización en forma sellada (PrunedFormOutsideSync), antes de cualquier trabajo de prueba.
  2. El identificador de cadena coincide.
  3. Forma y piso de comisión: una acción sin paquete no lleva ninguno, y todas las demás deben llevar exactamente uno; check_burn_shape fija cuál de los tres campos de quema puede establecer la acción: un TokenBurn o un BridgeBurn quema su propio asset y amount mediante burn_asset y burn_a, un Bond o un RegisterAggregator quema su monto mediante burn_r, y cualquier otra acción no quema nada; fee ≥ fee_floor(action). En una cadena con una sección gas (chain 20), el piso de un Call o de un Invoke en este paso es la regla de gas con un límite declarado de 1, BUNDLE_BASE + gas_price + byte_price × ⌈bytes / 1024⌉ sobre su prueba y su sobre de entrada, que se conocen antes de toda verificación.
  4. Ancla: una de las últimas 1.024 raíces de fin de bloque en la chain 20, cuyo génesis fija proof_window_blocks: 1024 (v0.6.8); una de las últimas 256 en una cadena sin ese campo, como hasta la chain 19.
  5. Tiempo: dentro de [height − 1024, height] en la chain 20; [height − 256, height] sin el campo. El único valor del génesis fija ambas ventanas.
  6. Nulificadores y compromisos: los cuatro nulificadores son distintos y ninguno está gastado; los cuatro compromisos son distintos y ninguno es ya una hoja.
  7. Verificaciones de la acción: el faucet está habilitado, el mint está por debajo del límite y firmado por un validador, y en la chain 20 nombra a un destinatario de la lista permitida staking.faucet_recipients del génesis, cabe en el faucet_budget_per_epoch de la época y está firmado por un validador de la lista staking.faucet_minters del génesis (una regla de validez desde la chain 16); un mint o un depósito igual o superior a 2⁶³ se rechaza en todas las cadenas; el programa se decodifica; el programa existe; las reglas de staking (el registro está presente exactamente cuando el validador es desconocido, el nonce, la firma, stake suficiente); las reglas propias del puente para BridgeAttest y BridgeBurn y para las acciones de pausa y de listado; las reglas de RPL para sus cuatro acciones, incluida la comisión de registro; en la chain 20, el quórum del voto de admisión y, para un Invoke, la forma de la transición, las lecturas declaradas frente a las celdas almacenadas, la cobertura de la bóveda para cada pago y la comisión de celda. Todo esto se ejecuta antes de la prueba del paquete, de modo que una transacción que no puede aplicarse no cuesta ninguna verificación STARK. Bajo hardening_v6 (chains 16 a 20) hay dos rechazos más en este paso: un Deploy de un programa que ninguna llamada podría contener (ProgramUncallable), y una prueba de paquete o de llamada cuyo encabezado o transcripción lleva un campo que el prover honesto no escribiría (non-canonical proof: …), rechazada antes de verificar cualquiera de las dos pruebas. Desde la v0.6.8, una prueba cuyo encabezado declara un grado superior al techo de la tabla más alta se rechaza primero con el mismo veredicto (auditoría v6 ZKV-4), antes de que la verificación la recorra.
  8. Digest del paquete: en una cadena de autorización dividida (toda cadena desde la 17) se comprueban primero los campos de autorización: se rechaza un paquete sin prueba de autorización, el c que publica la prueba de autorización (leído, aún no verificado) debe ser igual a auth_commit, y en la chain 20 la prueba de autorización debe declarar un GAS_LIMIT de exactamente 1.279. Después el ledger recalcula el digest de los campos publicados del paquete, auth_commit entre ellos, y debe ser igual a lo que publicó la prueba. En la chain 20 la prueba del paquete debe además declarar un GAS_LIMIT de exactamente el bundle_gas_limit del génesis, 20.479.
  9. Prueba del paquete: Machine::verify_public frente al hc_bundle fijado en el génesis y el binding de la transacción. En una cadena de autorización dividida, la prueba de autorización se verifica a continuación, frente al hc_auth fijado en el génesis y el mismo binding.
  10. Prueba de llamada y su comisión por nivel: para un Call o un Invoke, primero se fija el encabezado de la prueba (nivel como máximo 14, una tabla keccak como máximo de 2¹², una tabla sha256 como máximo de 2¹³, la altura del programa desplegado, con un piso de 2⁷ filas bajo hardening_v6, y en la chain 20 un GAS_LIMIT declarado no mayor que el techo gas_max del encabezado), después el STARK de la llamada frente al code_hash del programa y, bajo hardening_v6, el binding de llamada de la transacción. La comisión se comprueba al final, porque solo puede conocerse una vez decodificada la prueba: en la chain 20, fee ≥ BUNDLE_BASE + gas_price × GAS_LIMIT + byte_price × ⌈bytes / 1024⌉ a los precios vigentes, más cell_fee por cada celda creada en un Invoke (Comisiones); en una cadena sin sección gas, fee ≥ BUNDLE_BASE + call_fee(tier).

Los errores regresan de rand_sendTransaction con el código -32000 y el motivo: nullifier already spent, anchor is not one of the last 1024 roots (256 en una cadena sin proof_window_blocks), time 12 is outside [476, 1500], fee 1000000 below minimum 2000000, the bundle's digest is not what its proof published, invalid bundle proof: …, unknown program …, already in mempool, conflicts with a pending transaction over <nullifier>, faucet is disabled on this chain y, desde la chain 14, the bundle burns asset 2 on an action that burns no token, a burn of 5 is not allowed on this action, the bundle burns 399, not the 400 the action declares, wrong mint nonce: expected 1, got 0, wrong token index: expected 3, got 2, desde la chain 17 this chain requires an auth proof on every bundle (genesis hc_auth) y the auth proof publishes a different commitment than the bundle's auth_commit, y en la chain 20 envelope is 1348 bytes, this chain requires exactly 1860 y bundle proof declares gas limit …, this chain requires exactly 20479. Aceptación no es confirmación: consulte rand_getTransaction hasta que devuelva un bloque.

Un bloque que contiene cualquier transacción inválida es inválido. El mempool indexa cada nulificador y cada compromiso pendiente y rechaza de plano un conflicto, de modo que dos paquetes que gastan la misma nota nunca comparten bloque.

Tamaños

partebytes
Word832
un Envelope1.892 codificados (1.860 de texto cifrado) desde la chain 18; 1.380 (1.348) hasta la chain 17
Bundle sin sus dos pruebas7.936 (cuatro nulificadores, cuatro compromisos, cuatro sobres, auth_commit)
transacción de transferencia sin sus dos pruebas7.949
transacción de despliegue sin sus dos pruebas, programa de 100 palabras, sin entrada pública8.369
transacción de llamada sin sus tres pruebas, sin sobre de entrada7.990
transacción de mint (sin paquete)5.761 (una clave Dilithium2 de 1.312 bytes y una firma de 2.420 bytes)
una prueba de paquete, nivel 14, perfil de producción1.497.544 y 1.504.260 leídos en la chain 18 (un despliegue en la altura 97.821 y una llamada en la 98.335, 2026-09-30); 1.422.116 y 1.423.170 medidos en la chain 14 (el registro de zUSD y un listado de respaldo, 2026-09-20)
una prueba de autorización, nivel 10, perfil de producción1.370.827 y 1.367.303 en las mismas dos transacciones de la chain 18

Las primeras seis filas son la codificación desde la chain 18: el campo de memo añadió 512 bytes a cada sobre, y la autorización dividida añadió 40 bytes al paquete antes de los bytes propios de la prueba de autorización. Así, una transferencia blindada en la red ocupa unos 2,88 MB desde la chain 18, la chain 20 incluida, casi todo prueba, sea cual sea el activo que mueva: unos 1,5 MB de prueba de paquete y 1,37 MB de prueba de autorización. Hasta la chain 15 eran unos 1,43 MB, con una sola prueba. Los bloques están limitados a 2.000 transacciones (MAX_BLOCK_TXS) y a los max_block_bytes de la cadena en bytes de transacciones, ambas reglas de consenso: 4 MiB por defecto (MAX_BLOCK_BYTES), que alojarían una de esas transferencias, y 20 MiB en el génesis de la chain 20, que tiene espacio para siete. Un génesis con hc_auth debe fijar max_block_bytes en al menos tres veces max_proof_bytes más 1 MiB, puesto que una transacción puede llevar tres pruebas (paquete, autorización, llamada), por lo que allí se rechaza el valor por defecto de 4 MiB. La agregación a nivel de bloque es el remedio en cola; véase Pruebas.

Leerla de vuelta

rand_getTransaction(hash) devuelve null hasta que la transacción se confirma; después devuelve su posición en el bloque y solo los campos públicos:

{
  "height": 192, "index": 0, "block_hash": "63f6…08",
  "tx": {
    "hash": "4f2c…e7", "chain_id": 20,
    "bundle": {
      "anchor": "6b1d…c4",
      "nullifiers": ["8c04…d1", "5e77…20", "03aa…6f", "e19b…42"],
      "commitments": ["2a9f…07", "b310…88", "77c1…0e", "5d20…b3"],
      "fee": "1000000", "burn_a": "0", "burn_r": "0", "burn_asset": 0, "time": 5,
      "proof_len": 1497544, "envelope_len": [1860, 1860, 1860, 1860],
      "auth_commit": "0bab…e8a1", "auth_proof_bytes": 1370827
    },
    "action": { "kind": "none" }
  }
}

No hay campo from, to, nonce, importe ni asset en una transferencia, y tampoco en el bloque almacenado: el nodo no tiene nada más que censurar. auth_commit y auth_proof_bytes (la longitud de la prueba de autorización) están presentes desde la chain 17. El bundle siempre tiene cuatro ranuras, incluidas las ficticias, y tanto una transferencia de RAND como una transferencia de cualquier token RPL son "kind": "none". Todo importe u64 es una cadena decimal desde la chain 14 (fee, burn_a, burn_r, el amount de una acción); los índices, los nonces, las alturas y las longitudes siguen siendo números JSON. Los demás tipos de acción muestran sus campos públicos (mint, deploy, call, bond, unbond, withdraw, bridge_attest, bridge_burn, register_token, token_mint, set_authority, token_burn, pause_mints, unpause_mints, register_bridged_token, list_backing, rotate_pq_guardians, rotate_pause_key, los cuatro tipos de vesting claim_vested, revoke_vesting, bond_vested, unbond_vested y, desde v0.6.8, admit_validator, slash_equivocation, rotate_pq_guardians_v2, rotate_pause_key_v2, cancel_rotation e invoke), tal como se enumeran en la referencia de JSON-RPC.

Verificado por última vez con el commit c0878c3f del fullnode (cadena 21) el 2026-10-12. Cuando el código y esta página no coinciden, el código tiene razón; avísenos.