Mi respuesta:
Ok, el problema es realmente con Ganache... Si uso geth, todo está bien.
... ... perdón por tu tiempo ...
---------------- La pregunta original --------------------
Según tengo entendido, los saldos de tokens ERC20 se almacenan en la prueba de almacenamiento , lo que cambiará con el tiempo. Además, token.balanceOf(accountHash, {}, blockNumber)
parece devolver solo el saldo más reciente sin importar cuál blockNumber
sea. Me pregunto si la cadena Ethereum retrocede y luego crece a lo largo de una nueva cadena, ¿cómo se tratan los saldos de tokens ERC20?
Quiero aclarar un poco sobre el Rollback
aquí. Considere una cadena simplificada con solo 8 bloques, etiquetados por el orden en que se agregan a la cadena (no el número de bloque que define la altura del bloque).
# blocks are labeled by the order they are added to the chain
/--[6]<--[7]<--[8]
/
[1]<--[2]<--[3]<--[4]<--[5]
Digamos que hay transacciones sobre un token (ERC20) en todos estos bloques.
Cuando [5]
se agrega a la cadena, está en la cadena más larga y token.balanceOf['0xAA']
me da balance1
.
Ahora suponga [6][7][8]
que se agregan a [3]
, esta rama se convierte en la más larga y todas las transacciones en [4]
y [5]
se vuelven inválidas.
Ahora supongamos que quiero estar seguro, así que solo me importa el saldo de un token ERC20 (no ETH) en el bloque (N-4). ¿Cómo puedo obtener este saldo?
Hice mi búsqueda y la única forma es usar la API de etherscan, que no está bien para un uso intensivo. Hay otras personas aquí y allá que hacen preguntas similares y siento totalmente su frustración.
Gracias.
Actualización el 5 de abril.
Quiero dar más detalles sobre mis intentos hasta ahora.
1) Estoy usando Ubuntu 16.04 y geth 1.8.2 estable.
2) Empecé ejecutando Ganache, la aplicación con IU gráfica.
3) Mi token es casi el mismo que el del documento oficial https://ethereum.org/token .
4) Implementé el token usando eth.accounts[0]
en geth (ganache genera 10 cuentas y cada una tiene 100 ETH iniciales para mí)
$ geth attach http://localhost:8545
var tokenABI = [...];
var tokenFactory = eth.conract(tokenABI);
var byteCode = "0x" + "606..."
var token = tokenFactory.new(
100,
"TestCoin",
"TSC",
{
from: eth.accounts[0], // owner
data: byteCode,
gas: 4700000
}, function(e, contract) {});
5) Hice las siguientes transacciones:
// 3 ETH transactions
eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(5, "ether") });
eth.sendTransaction({from: eth.accounts[1], to: eth.accounts[2], value: web3.toWei(3, "ether") });
eth.sendTransaction({from: eth.accounts[2], to: eth.accounts[3], value: web3.toWei(1, "ether") });
// 3 token transfers
token.transfer(eth.accounts[1], web3.toWei(5, 'ether'), { from: eth.accounts[0] }, function(err, contract) {})
token.transfer(eth.accounts[2], web3.toWei(3, 'ether'), { from: eth.accounts[1] })
token.transfer(eth.accounts[3], web3.toWei(1, 'ether'), { from: eth.accounts[2] })
Para el token, espero que el saldo final sea
account 0: 95
account 1: 2
account 2: 2
account 3: 1
My eth.blockNumber
muestra 7 bloques, lo cual es correcto (3 transferencias éticas, 1 creación de contrato, 3 transferencias de tokens). Cualquier saldo de la cuenta 3 es definitivamente menor que 1 en los bloques anteriores. Sin embargo, el siguiente comando me devuelve 1 éter (en unidades de Wei):
> token.balanceOf(eth.accounts[3], 0, function(err, res) {console.log(err, res};)
null 1000000000000000000
undefined
No importa cómo cambie ese número, de 0 a 7, siempre obtengo el mismo resultado.
Por cierto, no tengo problemas para recuperar la retención de ETH en bloques anteriores. Esto solo ocurre con el Token. Una cosa que noté es que mis eth.syncing
devoluciones false
, ¿tal vez porque estoy usando Ganache?
Primero aclaremos esta reversión. En el ejemplo que proporciona, se agregan dos bloques (4 y 5) a la cadena. Sin embargo, también se extrae una cadena separada, lo que genera (6,7,8) y, por lo tanto, se hace cargo de la cadena con 4 y 5. Si la red funciona normalmente, podría suceder que aproximadamente al mismo tiempo dos mineros creen un bloque y envíen ellos en la red. En ese momento, no está claro cuál es el bloque 'real' y, por lo tanto, estamos en una bifurcación de la red.
En el ejemplo proporcionado, se agrega otro bloque 5, pero de repente un minero ha generado 5, 6 y 7 y los publica, que ahora es la cadena más larga. Esto implica que este minero tiene >50% del hashrate de la red. Sin embargo, debido a la "suerte", esto puede suceder a veces y, por lo tanto, si desea que sus transacciones se verifiquen de forma segura, debe esperar algunos bloques antes de confirmar esta transacción "de verdad". (Por ejemplo, si envía ETH a alguien, espere 10 bloques y en ese momento es muy difícil para los "mineros malvados" retomar).
Ahora la segunda pregunta, que básicamente se reduce a "¿cómo puedo obtener el saldo de X en un bloque determinado?". Básicamente, desea ejecutar una función en un determinado bloque. Esto se puede hacer a través de web3. Primero genera un objeto de contrato y luego puede usar (javascript)
ERC20Contract.balanceOf(address, BlockNumber, function(){})
(El ejemplo anterior se usa ERC20Contract
como dirección de contrato, balanceOf
es la función de contrato que devuelve el saldo de address
, BlockNumber
es el bloque real que desea buscar y la función vacía es una función de devolución de llamada (algunas implementaciones de web3 como MetaMask las necesitan))
(Consulte: https://github.com/ethereum/wiki/wiki/JavaScript-API en Métodos de contrato)
ERC20Contract.balanceOf(address, BlockNumber, function(){})
, no importa lo que BlockNumber
especifique, siempre obtengo el mismo número: el último saldo. Mi entorno de prueba es Ganache + geth + javascript web3.
JBrouwer
Nulik
rollback
en blockchains. Puede que te estés refiriendo a la división de la cadena, cuando alguien extrae 2 tenedores de una cadena de bloques. La cadena más larga gana, y el nodo simplemente elimina la cadena más corta y cambia a la cadena más larga. Los tokens son variables en el estado, por lo que se eligen las variables en la cadena más larga, eso es todo.kurtz
JBrouwer
token.balanceOf(accountHash, {}, blockNumber)
? No tiene sentido para mí que esta función deba existir en la cadena. Además, todo el almacenamiento se revierte cuando se bifurca la cadena; así mapeos también. Las reversiones de la cadena Ethereum nunca deberían ocurrir, esto arruina toda la idea detrás de Ethereum, ya que ahora una organización centralizada puede optar por hacer una "bifurcación dura" de toda la cadena.kurtz
balanceOf
función, lo leí aquí ethereum.stackexchange.com/questions/42783/…kurtz