Как выполнить транзакцию тестовой сети на Android с помощью Geth 1.5.9?

Я пытаюсь создать DApp на Android с помощью Geth 1.5.9. После некоторых исследований и написания кода мне удалось найти информацию для установки/запуска узла geth, а также для создания некоторых учетных записей в Android Studio.

Я более или менее следовал инструкциям официальной Wiki и презентации Devcon2 — я знаю, что они не обновлены, но до сих пор мне этого было достаточно.

В любом случае, я хотел бы попробовать транзакцию сейчас, поэтому я попытался выполнить транзакцию с Account1 на Account2. Итак, я пошел в Ropsten-Faucet и получил немного эфира для обеих учетных записей, а затем попытался закодировать метод транзакции «sendTransaction», но у меня возникли некоторые проблемы с тем, чтобы сделать это правильно.

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

03-09 16:03:36.542 24705-24766/ch.zhaw.zendrio V/MainActivity: Start startSync
03-09 16:03:36.544 24705-24766/ch.zhaw.zendrio I/MainActivity: Start Transaction
03-09 16:03:36.545 24705-24766/ch.zhaw.zendrio I/MainActivity: Account1: 0xfa1c40e42d7317cd2a1b9cc88c9182e3c5efda5d
03-09 16:03:36.546 24705-24766/ch.zhaw.zendrio I/MainActivity: Account2: 0x8a9519da1f03e1fd5a558a6d43dc4ba06f1f955d
03-09 16:03:36.546 24705-24766/ch.zhaw.zendrio I/MainActivity: Nonce used:0
03-09 16:03:39.488 24705-24766/ch.zhaw.zendrio I/MainActivity: Cost: 2
03-09 16:03:39.488 24705-24766/ch.zhaw.zendrio I/MainActivity: GasPrice: 1
03-09 16:03:39.488 24705-24766/ch.zhaw.zendrio I/MainActivity: Gas: 1
03-09 16:03:39.488 24705-24766/ch.zhaw.zendrio I/MainActivity: Nonce: 0
03-09 16:03:39.490 24705-24766/ch.zhaw.zendrio I/MainActivity: Value: 1
03-09 16:03:39.490 24705-24766/ch.zhaw.zendrio I/MainActivity: Sig-Hash Hex: 0x300eb1c450fe26f71e13bdbf099b8a70f3015e069ef1fd9e0598e6c21c0b4224
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio I/MainActivity: Hash Hex: 0xdf050dcf9f8e2f508addab5a0359923b0a15689184732b84b7f10e3994ce6f1f
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio I/MainActivity: Data-Length: 11
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio I/MainActivity: To: 0x8a9519da1f03e1fd5a558a6d43dc4ba06f1f955d
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio V/MainActivity: invalid transaction v, r, s values
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio W/System.err: go.Universe$proxyerror: invalid transaction v, r, s values
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio W/System.err:     at org.ethereum.geth.Transaction.getFrom(Native Method)
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio W/System.err:     at ch.zhaw.zendrio.view.activity.MainActivity.sendTransaction(MainActivity.java:136)
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio W/System.err:     at ch.zhaw.zendrio.view.activity.MainActivity.access$300(MainActivity.java:24)
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio W/System.err:     at ch.zhaw.zendrio.view.activity.MainActivity$2.run(MainActivity.java:88)
03-09 16:03:39.491 24705-24766/ch.zhaw.zendrio W/System.err:     at java.lang.Thread.run(Thread.java:761)

И вот где я застрял на несколько дней, и мне нужна помощь от вас, ребята.

Я использовал следующие тест-аккаунты и код ниже в полях:

  • Аккаунт1: 0xfa1c40e42d7317cd2a1b9cc88c9182e3c5efda5d
  • Учетная запись 2: 0x8a9519da1f03e1fd5a558a6d43dc4ba06f1f955d

Какие могут быть у меня проблемы:

  1. Синхронизация Testnet-Node: Возможно, я что-то неправильно понял в подключении к ropsten-testnet при настройке узла. Насколько я понимаю, я думал, что достаточно изменить EthereumNetworkId на 3, чтобы подключиться к ropsten и использовать значения по умолчанию для остальной части конфигурации узла. См. Метод "startNode". Но я думаю, что синхронизация не работает, и я на самом деле не знаю, почему. Если я использую основную сеть, я вижу, что синхронизация начинается, но не в тестовой сети. Итак, что я пропустил в конфигурации узла?

    private Node startNode() throws Exception {
        final NodeConfig nodeConfig = new NodeConfig();
        nodeConfig.setEthereumNetworkID(3); // Is this enough to connect to Ropsten??
        Log.v(TAG, "Start Node");
        Node node = Geth.newNode(getFilesDir() + "/.ethereum", nodeConfig);
        node.start();
        final NodeInfo nodeInfo = node.getNodeInfo();
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // Show the config in the UI
                final TextView textbox = (TextView) findViewById(R.id.GethTextbox);
                textbox.append("My name: " + nodeInfo.getName() + "\n");
                textbox.append("My address: " + nodeInfo.getListenerAddress() + "\n");
                textbox.append("My protocols: " + nodeInfo.getProtocols() + "\n");
                textbox.append("My ID: " + nodeInfo.getID() + "\n");
                textbox.append("My ListenerPort: " + nodeInfo.getListenerPort() + "\n");
                textbox.append("My IP: " + nodeInfo.getIP() + "\n\n");
                textbox.append("NodeConfig: " + nodeConfig.toString() + "\n\n");
            }
        });
        return node;
    }

    private void startSync(Node node) throws Exception {
        //TODO Refactor/Delete
        Log.v(TAG, "Start startSync");
        ctx = new Context();
        final TextView blockTextBox = (TextView) findViewById(R.id.blockTextBox);
        ec = node.getEthereumClient();
        //blockTextBox.append("Latest block: " + ec.getBlockByNumber(ctx, -1).getNumber() + ", syncing...\n");
        NewHeadHandler handler = new NewHeadHandler() {
            @Override
            public void onError(String error) {
                Log.e(TAG, error);
            }

            @Override
            public void onNewHead(final Header header) {
                MainActivity.this.runOnUiThread(new Runnable() {
                    public void run() {
                        blockTextBox.append("#" + header.getNumber() + ": " + header.getHash().getHex().substring(0, 10) + "…\n");
                    }
                });
            }
        };
        ec.subscribeNewHead(ctx, handler, 16);
    }
  1. Подписание транзакции: возможно, я сделал что-то не так с процессом подписания или с выбранными значениями транзакции.
    • Итак, первая проблема, с которой я столкнулся, была, когда я хотел получить одноразовый номер. На самом деле я не уверен, нужно ли мне получить его с помощью ec.getPendingNonceAt(..) или я могу просто установить случайный, но я знаю, что когда я использую getPendingNonceAt(..), он блокирует мой поток . Это потому что я не синхронизировался? Если я использую случайный одноразовый номер = 0, я получаю недопустимую ошибку транзакции. Что, вероятно, должно произойти.
    • Затем второй проблемой была сама подпись с помощью keyStore.signTx(..), потому что для этого требуется BigInt в качестве третьего параметра, и мне очень жаль, но я не нашел никакой ссылки на то, что нужен третий параметр. Я даже изучил JavaScript и API Ethereum-Go-Doc, чтобы выяснить, каким может быть этот параметр. Пожалуйста, кто-нибудь скажите мне или дайте мне JavaDoc.

    private void sendTransaction() throws Exception {
        Log.i(TAG,"Start Transaction");
        KeyStore keyStore = new KeyStore(this.getFilesDir() + "/keystore",
                Geth.StandardScryptN, Geth.StandardScryptP);
        Accounts accounts = keyStore.getAccounts();
        if(accounts.size() >= 2){
            account1 = accounts.get(0);
            account2 = accounts.get(1);
        }
        Log.i(TAG, "Account1: " + account1.getAddress().getHex()); //Sender
        Log.i(TAG, "Account2: " + account2.getAddress().getHex()); //Receiver

        BigInt value = Geth.newBigInt(1);
        BigInt gasLimit = Geth.newBigInt(0);
        BigInt gasPrice = Geth.newBigInt(0);
        String testData = "Hello World";
        byte[] data = testData.getBytes();

        long nonce = ec.getPendingNonceAt(ctx, account1.getAddress()); // 1. Blocks the Thread if used? Syncing maybe?
        //long nonce = 0x00;
        Log.i(TAG, "Nonce used:" + nonce);
        Transaction transaction = Geth.newTransaction(nonce, account2.getAddress(), value, gasLimit, gasPrice, data);

        keyStore.timedUnlock(account1, "test", 10000000);
        transaction = keyStore.signTx(account1, transaction, new BigInt(0)); // 2. Why BigInt needed?

        Log.i(TAG, "Cost: " + transaction.getCost());
        Log.i(TAG, "GasPrice: " + transaction.getGasPrice());
        Log.i(TAG, "Gas: " + transaction.getGas());
        Log.i(TAG, "Nonce: " + transaction.getNonce());
        Log.i(TAG, "Value: " + transaction.getValue());
        Log.i(TAG, "Sig-Hash Hex: " + transaction.getSigHash().getHex());
        Log.i(TAG, "Hash Hex: " + transaction.getHash().getHex());
        Log.i(TAG, "Data-Length: " + transaction.getData().length);
        Log.i(TAG, "To: " + transaction.getTo().getHex());
        Log.i(TAG, "Sender: " + transaction.getFrom().getHex()); // 3. Produces the Error-Output.

        ec.sendTransaction(ctx, transaction);
    }

Извините за длинный пост и спасибо за помощь!

Ответы (1)

Я не уверен, но потенциально есть три проблемы:

  1. Вам понадобится доступ к блоку генезиса Ropsten для правильной синхронизации, хотя я думаю, что geth каким-то образом сможет сделать это за вас. (Это происходит на ПК.) Тем не менее, Ropsten сейчас более или менее сломан из-за атак. Вам больше повезет, если вы создадите частную цепочку, как описано здесь .

  2. Этот одноразовый номер должен точно совпадать с текущим одноразовым номером учетной записи, иначе его нельзя будет майнить. Если учетные записи новые, это значение обычно равно нулю. Однако я считаю, что одноразовые номера тестовой сети начинаются с другого числа, чтобы избежать повторных атак. (Частные тестовые сети работают как обычно.)

  3. Я предполагаю, что BigInt, вероятно, должно быть 3 из-за этого раздела в коде geth. Я предполагаю, что это связано с предотвращением повторных атак .

Наконец (я думаю, вы столкнетесь с этим позже), ваш газ и цена газа слишком низки. газ должен быть не менее 2300 (IIRC), чтобы даже выполнить транзакцию. gasPrice обычно составляет около 20 Gwei, и я предполагаю, что он запрашивает цену в wei.

Спасибо, я попробую это
Итак, сначала я попытался добавить блок Genesis в файл nodeconfig. Новый geth-лог теперь содержит запись «Начата синхронизация блоков», что, я думаю, хорошо, потому что теперь я получаю none (0) через ec.getPendingNonceAt(..). Я также изменил gas и gasPrice на указанные вами значения, но все равно получаю ошибку транзакции.
Я также пытался сделать это с частной сетью, но потерпел неудачу, когда дело дошло до подключения эмулятора Android к сети. Я не знаю почему, но мой Android-клиент не мог подключиться к майнеру или узлу, даже когда я добавлял их как загрузочные узлы.
К сожалению, я не знаком с Android-разработкой, поэтому не знаю, чем помочь дальше. :(