¿Por qué no puedo usar múltiples variables de tamaño dinámico en Solidity?

El siguiente fragmento de código no funciona.

pragma solidity ^0.4.11;

contract Test1 {
    uint[] public a;
    uint[] public b;

    function putX(uint x) public {
        a.push(x);
        b.push(block.number);
    }

    function getA() public view returns (uint[]) {
        return a;
    }

    function getB() public view returns (uint[]) {
        return b;
    }
}

Producción:

> test1.putX.sendTransaction(11, {from: eth.accounts[0]})
> test1.getA()
[]
> test1.getB()
[]

El siguiente fragmento de código, por el contrario, funciona.

pragma solidity ^0.4.11;

contract Test2 {
    uint[2][] public a;

    function putX(uint x) public {
        a.push([x, block.number]);
    }

    function getA() public view returns (uint[2][]) {
        return a;
    }
}

Producción:

> test2.putX.sendTransaction(12, {from: eth.accounts[0]})
> test2.getA()
[[12, 1151]]

Me pregunto por qué... estoy usando el último geth estable (1.7)

También traté de usar una matriz de tamaño dinámico + una asignación, y tampoco funciona.

Incluso dudo que el código del documento oficial pueda funcionar, ya que utiliza múltiples variables de tamaño dinámico:

https://solidity.readthedocs.io/en/develop/solidity-by-example.html

¿Alguien sabe por que pasó esto?

Funciona, puede devolver una matriz de tamaño dinámico. Probé tu ejemplo contra remix.ethereum.org y funcionó como se esperaba. ¿ Estás seguro de que tu putXtransacción fue minada antes de llamar getA? ¿Está utilizando web3 v1.0 o v0.20, o truffle? Algunos de ellos devuelven una promesa y tienes que esperar a que se formen antes de llamar al captador.
Funciona en Remix, sí, también lo he probado. Pero no funciona con la última versión estable de geth (1.7) (construí una red privada en una máquina con un minero, la primera no funciona, la segunda funciona).

Respuestas (1)

Probé su código con ambos remix, geth v1.7.2 y v1.7.3 y ambos funcionan como se esperaba.

Tal vez su problema es que está haciendo la consulta antes de que se extraiga la transacción. Eso hará que el contrato vuelva al estado anterior.

¿En realidad? ¡Seguí preguntando durante más de 2 horas! ¡Y todavía no tenía nada allí! Qué raro... por qué funciona en tu entorno... emmm...
Es una funcionalidad bastante básica, por eso tengo curiosidad por qué no funciona. ¿Está seguro de que la transacción se ha extraído y se ejecutó correctamente? Quizás se quede sin gasolina. La devolución de matrices de tamaño dinámico debería estar bien, no puede devolver matrices dinámicas anidadas, es decir, una matriz de cadenas fallará, pero una matriz de int o uint debería estar bien.
Veo lo que pasó. Tienes razón. Después de cambiar: "test1.putX.sendTransaction(11, {from: eth.accounts[0]})" a "test1.putX.sendTransaction(11, {from: eth.accounts[0], gas: 200000000}) ", ¡funcionó! ¡La cantidad predeterminada de gas no fue suficiente! ¡No me di cuenta de que test1.putX() consume tanta gasolina! Pero test2.putX() funciona, por lo que no consume menos gas que test1.putX()... Hmm...
¿Existe algún archivo de registro o algo similar del que pueda conocer el estado de las transacciones que he enviado?
Aquí está el artefacto producido por truffle compilado con Solidity v0.4.18 (solc-js) gist.github.com/anonymous/fdc0ef75669ab57e40a84faf1bea9a03 . Puede examinar la ejecución de una transacción de geth con debug.traceTransaction(txhash), de byzantinum eth.getTransactionReceipt(hash)tiene un campo de 'estado' que indica que la transacción se ejecutó correctamente o se revirtió.