Почему я не могу использовать в Solidity несколько переменных с динамическим размером?

Следующий фрагмент кода не работает.

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;
    }
}

Выход:

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

Следующий фрагмент кода, напротив, работает.

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;
    }
}

Выход:

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

Мне интересно, почему... Я использую последнюю стабильную версию geth (1.7)

Я также пытался использовать массив с динамическим размером + сопоставление, и это тоже не работает.

Я даже сомневаюсь, что код в официальном документе может работать, поскольку он использует несколько переменных с динамическим размером:

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

Кто-нибудь знает, почему это произошло?

Это работает, вы можете вернуть массив динамического размера. Я попробовал ваш пример с remix.ethereum.org, и он работает, как и ожидалось. Вы уверены, что ваша putXтранзакция была заминирована до звонка getA? Вы используете web3 v1.0 или v0.20, или трюфель? Некоторые из них возвращают обещание, и вам нужно подождать, прежде чем вызывать геттер.
В Remix работает, да, я тоже пробовал. Но не работает с последней стабильной версией geth (1.7) (собирал приватную сеть на одной машине с одним майнером, первый не работает, второй работает.)

Ответы (1)

Я пробовал ваш код с обоими ремиксами, geth v1.7.2 и v1.7.3, и оба они работают, как и ожидалось.

Возможно, ваша проблема заключается в том, что вы делаете запрос до того, как транзакция будет добыта. Это заставит контракт вернуться в предыдущее состояние.

Действительно? Я продолжал запрашивать более 2 часов! И там еще ничего не было! Странно... почему это работает в вашей среде... эммм...
Это довольно простая функция, поэтому мне любопытно, почему она не работает. Вы уверены, что транзакция была добыта и успешно выполнена? Возможно, у него кончился бензин. Возвращать массивы динамического размера должно быть хорошо, вы не можете возвращать вложенные динамические массивы, т.е. массив строк не будет работать, но массив int или uint должен быть в порядке.
Я вижу, что произошло. Ты прав. После того, как я изменил: "test1.putX.sendTransaction(11, {from: eth.accounts[0]})" на "test1.putX.sendTransaction(11, {from: eth.accounts[0], gas: 200000000}) ", это сработало! Установленного по умолчанию количества газа не хватило! Я не знал, что test1.putX() потребляет столько газа! Но test2.putX() работает, так что потребляет не меньше газа, чем test1.putX()... Хм...
Есть ли какой-либо файл журнала или что-то подобное, из которого я могу узнать статус транзакций, которые я отправил?
Вот артефакт, созданный truffle, скомпилированный с помощью Solidity v0.4.18 (solc-js) gist.github.com/anonymous/fdc0ef75669ab57e40a84faf1bea9a03 . Вы можете проверить выполнение транзакции от geth с помощью debug.traceTransaction(txhash), у byzantinum eth.getTransactionReceipt(hash)есть поле «статус», которое указывает, что транзакция была выполнена правильно или отменена.