¿Qué es un chainID en Ethereum, en qué se diferencia de NetworkID y cómo se usa?

Aquí se describe en la implementación go de Ethereum.

type ChainConfig struct {
    ChainId *big.Int `json:"chainId"` // Chain id identifies the current chain and is used for replay protection

Unas cuantas preguntas:

  1. ¿Cómo es diferente a networkID?
  2. ¿Se necesita chainIDy networkIDen cada bloque o solo en el bloque de génesis?
  3. ¿Puede dar un ejemplo específico de lo que significa cuando dice que chainIDse usa "para protección de reproducción"?

EDITAR: Aún sin respuesta:

¿Qué pasaría en la situación en la que estableces networkIDuna de las redes principales networkID, pero cambias las otras variables de configuración a lo que quieras? ¿Por qué importa lo que establezca para networkID si está ejecutando una cadena local?

Mis transacciones de Uniswap no pueden realizarse porque dice no chainid. ¿Cómo soluciono esto?

Respuestas (4)

¿En qué se diferencia de networkID?

ChainID se introdujo en EIP-155 para evitar ataques de repetición entre las principales cadenas ETH y ETC, que tienen un networkID de 1.

Básicamente es solo una forma adicional de diferenciar las cadenas. Después de EIP-155, ETH tiene un ID de cadena de 1, mientras que ETC tiene un ID de cadena de 61(aunque todavía tienen el mismo ID de red de 1).

¿Se necesitan chainID y networkID en cada bloque o solo en el bloque de génesis?

Se requiere para que la cadena funcione en general; por ejemplo, se requiere al firmar transacciones, lo que significa que las transacciones firmadas en la red ETH terminan con un hash diferente al de las firmadas en ETC. Antes de EIP-155, las transacciones firmadas en cada red tenían el mismo aspecto y podían reproducirse.

Editar:

Un ejemplo específico de cómo se usa chainId.

Según la página EIP-155 , el vvalor de la firma de una transacción depende del valor de chainID.

Si block.number >= FORK_BLKNUMy v = CHAIN_ID * 2 + 35o v = CHAIN_ID * 2 + 36, entonces, al calcular el hash de una transacción con fines de firma o recuperación, en lugar de aplicar hash solo a los primeros seis elementos (es decir, nonce, gasprice, startgas, to, value, data), hash nueve elementos, con vreemplazados por CHAIN_ID, r = 0y s = 0. El esquema de firma actualmente existente que usa v = 27y v = 28sigue siendo válido y continúa operando bajo las mismas reglas que lo hace ahora.

Hay un ejemplo detallado de cómo se aplica esto en la página EIP-155.

¿Puede explicar cómo funciona esto a nivel granular? Agradezco la respuesta, pero no estoy más cerca de entender cómo funciona al firmar, por qué el hash sería diferente, etc.
He agregado algunos detalles adicionales (esencialmente copiados de la página EIP-155). :-)
Usted dice "Se requiere que la cadena funcione en general", pero ¿cómo sabe una transacción al final de la cadena sobre las variables, como chainIDen el bloque de génesis?
Un cliente no puede operar sin saber en qué red (es decir, la combinación de networkID y chainID) está operando. Para iniciar en una red, la información de génesis de un cliente debe coincidir con el resto de la red. Tenga en cuenta que técnicamente no hay un "bloque de génesis". En realidad, es solo una definición de estado en un archivo JSON, uno de cuyos campos es el ID de cadena. (El primer bloque fue el bloque 0, y era solo un bloque normal, como todos los bloques posteriores, con la excepción de que creo que fue creado a mano y no extraído).
Por lo tanto, el cliente tiene la información de génesis, en su correo electrónico, a genesis.jsonla que puede consultar cuando la necesite. (En el arranque, es probable que lea el estado de génesis del disco en un conjunto de variables en la memoria. Sin embargo, no he mirado la ruta del código para confirmar).
Correcto, pero si un minero obtiene una transacción de un nodo diferente , ¿cómo puede saber el minero si el archivo de génesis en ese otro nodo coincide con el de su nodo de minería?
Porque cuando recibe la transacción, recupera el vvalor y, en última instancia, el valor de chainID, no coincidirá con el suyo. (De eso se trata EIP-155).

A pesar de que esta pregunta tiene una respuesta aceptada, la pregunta original no parece estar respondida, así que agregaré mis dos centavos.

  1. ¿En qué se diferencia de networkID?

El identificador de red (networkID) evita que un nodo se conecte a los nodos que se sincronizan con otras redes. Cuando se establece la conexión entre dos nodos, estos nodos intercambian mensajes de estado que, entre otras cosas, contienen identificadores de red de los nodos emisores. Según la documentación, el Statusmensaje "debe enviarse justo después de que se establezca la conexión y antes de cualquier otro mensaje de protocolo eth". Cuando un nodo recibe un Statusmensaje de su par, compara el identificador de red en el mensaje con el identificador de red del propio nodo y finaliza las conexiones en caso de discrepancia.

El identificador de cadena (chainID) introducido en EIP-155 protege la transacción incluida en una cadena para que no se incluya en otra cadena. Básicamente, el identificador de cadena es un número entero que se utiliza en los procesos de firma de transacciones y verificación de firmas de transacciones. Si se utilizan diferentes identificadores de cadena para firmar y verificar la transacción, la verificación de la transacción fallará.

  1. ¿Se necesitan chainID y networkID en cada bloque o solo en el bloque de génesis?

La identificación de la red no se incluye en los bloques, ni se usa al firmar transacciones o extraer bloques. Es solo un atributo del protocolo Ethereum Wire que evita que los nodos de diferentes cadenas se conecten entre sí. El ID de la cadena no se incluye en los bloques, pero se usa durante los procesos de verificación y firma de transacciones, protegiendo de manera efectiva las transacciones que apuntan a que una cadena aparezca en otra cadena.

  1. ¿Puede dar un ejemplo específico de lo que significa cuando dice que chainID se usa "para protección de reproducción"?

Si dos cadenas usan identificadores de cadena diferentes para verificar transacciones, o si una cadena implementó EIP-155 y la otra cadena no lo implementó, esas dos cadenas nunca aceptarán la misma transacción. Esto protege de manera efectiva contra ataques de reproducción, es decir, de la situación en la que una transacción que se pretendía ejecutar en una cadena también se ejecutó en otra cadena.

- ¿En qué se diferencia de networkID?

networkId es para la comunicación del nodo y chainId se usa para la identificación de la cadena de destino en la firma: ETC y ETH chainId es diferente y networkId es el mismo

- ¿Se necesita chainID y networkID en cada bloque o solo en el bloque de génesis?

Esto está solo en el archivo de génesis, no en bloques. Aquí está la descripción del primer bloque de la red principal (sí, actualmente estoy sincronizando en modo rápido: D)

> eth.getBlock(0)
{
  difficulty: 17179869184,
  extraData: "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
  gasLimit: 5000,
  gasUsed: 0,
  hash: "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3",
  logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  miner: "0x0000000000000000000000000000000000000000",
  mixHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  receiptsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
  size: 540,
  stateRoot: "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544",
  timestamp: 0,
  totalDifficulty: 17179869184,
  transactions: [],
  transactionsRoot: "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
  uncles: []
}

> web3.eth.chainId()
"0x5b7d"

- ¿Puede dar un ejemplo específico de lo que significa cuando dice que chainID se usa "para protección de reproducción"?

Puede encontrar su respuesta aquí

¿Qué sucedería en la situación en la que establece networkIDuno de los ID de red de la red principal, pero cambia las otras variables de configuración a lo que quiera? ¿Por qué importa lo que establezca networkIDsi está ejecutando una cadena local?
Mi conocimiento sobre este tema no es lo suficientemente bueno para responder eso. Solo puedo decirte que no importa el ID de cadena, geth usa todo el archivo de génesis para verificar si dos pares están usando la misma cadena.
¿Puede dar más detalles sobre la distinción entre el archivo de génesis y el primer bloque? ¿Cómo usa blockchain esta información si no está almacenada en el primer bloque?
Geth simplemente revisa genesis.json y compáralo con el de la persona que intenta conectarse, eso es todo. Además, el archivo de génesis es una descripción de la cadena desde el principio. El primer bloque es solo un bloque que usa esta descripción, luego continúa.
Sí, pero ¿qué sucede si el archivo de génesis dice algo como "Fork at block 20000", lo cual es cierto? ¿Cómo sucede eso si solo se lee al principio? ¿No es necesario leerlo todo el tiempo?
Me está costando mucho entender las transacciones que ocurren en el primer bloque (siempre las mismas), el archivo de estado de génesis y, si se acepta un nuevo EIP, cómo cambia el aspecto de la cadena de bloques.
¿Qué quieres decir con "tenedor en el bloque 20000"? El génesis no puede decir "oye, quiero un tenedor en este bloque"
Habrá una transacción solo si alguien envió una. ¿Por qué crees que sería diferente? Es solo un bloque normal @AlwaysQuestioning
En la descripción chainIDno aparece @Florian Castelain
Otras respuestas afirman que chainID y networkID son cosas diferentes con diferentes propósitos. ¿Esta respuesta es incorrecta?

¿Qué pasaría en la situación en la que estableces networkID en uno de los networkID de la red principal, pero cambias las otras variables de configuración a lo que quieras? ¿Por qué importa lo que establezca para networkID si está ejecutando una cadena local?

Para tener una cadena verdaderamente local, debe establecer --bootnodesque apunte a uno de sus nodos. A qué bootnode(s) se conecta un nodo determina qué pares ve. Luego, la identificación de la red determina con qué pares (de los que ve) se conecta.

Entonces, si configura --bootnodesuno de sus nodos, puede configurar la identificación de la red como desee: ahora está separado de la red pública de Ethereum.

Si no configura --bootnodesuno de sus nodos:

En este caso, realmente no tiene una cadena completamente local: está conectado a todos los pares en la red pública de Ethereum que usan la misma identificación de red que usted.

No tiene claro lo que quiere decir con "otras variables de configuración". Si te refieres a la identificación de la cadena o al contenido del bloque de génesis, tu nodo aún se conectará a los pares en los mismos nodos de arranque con la misma identificación de red, pero el hash del bloque de génesis (y todos los bloques posteriores) no coincidirá, y el nodo se siente bastante solo... tendrá dificultades para encontrar un compañero con el que pueda intercambiar datos de blockchain.