Как правильно отправить вызов RPC с помощью Golang, чтобы получить владельца смарт-контракта? - PullRequest
0 голосов
/ 10 ноября 2018

Обновление

Поскольку я не могу достичь этого, используя подход, описанный в этом вопросе, я создал свою собственную библиотеку, чтобы сделать то же самое ( ссылка ). Он не зависит от пакета go-ethereum, а использует обычный пакет net/http для выполнения запроса JSON RPC.

Я все еще люблю знать, что я сделал неправильно в моем подходе ниже.


Определения

  • владелец = public переменная в контракте с address тип
  • контракт = смарт-контракт с владельцем

Это прокручиваемый запрос на получение владельца контракта. Мне удалось получить владельца. ( JSON RPC документы )

curl localhost:8545 -X POST \
--header 'Content-type: application/json' \
--data '{"jsonrpc":"2.0", "method":"eth_call", "params":[{"to": "0x_MY_CONTRACT_ADDRESS", "data": "0x8da5cb5b"}, "latest"], "id":1}'

{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000_OWNER"}

Но когда я пытаюсь скопировать его в Golang (код ниже), я получаю json: не могу распаковать строку в значение Go типа main.response error. ( код go-ethereum, который я использую )

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/ethereum/go-ethereum/rpc"
)

func main() {
    client, err := rpc.DialHTTP(os.Getenv("RPC_SERVER"))
    if err != nil {
        log.Fatal(err)
    }
    defer client.Close()

    type request struct {
        To   string `json:"to"`
        Data string `json:"data"`
    }

    type response struct {
        Result string
    }

    req := request{"0x_MY_CONTRACT_ADDRESS", "0x8da5cb5b"}
    var resp response
    if err := client.Call(&resp, "eth_call", req, "latest"); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%v\n", resp)
}

Что мне здесь не хватало?

Ожидаемый результат:

Адрес в строковом формате. Например. 0x3ab17372b25154400738C04B04f755321bB5a94b

P / S - мне известно о abigen , и я знаю, что лучше и проще сделать это, используя abigen. Но я пытаюсь решить эту конкретную проблему, не используя abigen метод.

Ответы [ 4 ]

0 голосов
/ 12 ноября 2018

Вы можете решить эту проблему наилучшим образом, используя go-ethereum / ethclient :

package main

import (
    "context"
    "log"

    "github.com/ethereum/go-ethereum"
    "github.com/ethereum/go-ethereum/common"
    "github.com/ethereum/go-ethereum/ethclient"
)

func main() {
    client, _ := ethclient.Dial("https://mainnet.infura.io")
    defer client.Close()

    contractAddr := common.HexToAddress("0xCc13Fc627EFfd6E35D2D2706Ea3C4D7396c610ea")
    callMsg := ethereum.CallMsg{
        To:   &contractAddr,
        Data: common.FromHex("0x8da5cb5b"),
    }

    res, err := client.CallContract(context.Background(), callMsg, nil)
    if err != nil {
        log.Fatalf("Error calling contract: %v", err)
    }
    log.Printf("Owner: %s", common.BytesToAddress(res).Hex())
}
0 голосов
/ 10 ноября 2018

json: не удается отменить сортировку строки в значении Go типа main.response error. Я получил аналогичную ошибку типа, когда я отменял маршализацию ответа. Это потому, что ответом была строка json, я имею в виду, что в качестве первого символа была цитата ". Поэтому, чтобы убедиться, что вы также столкнулись с той же проблемой, пожалуйста, printf("%v",resp.Result) перед демаршалированием здесь https://github.com/ethereum/go-ethereum/blob/1ff152f3a43e4adf030ac61eb5d8da345554fc5a/rpc/client.go#L278.

0 голосов
/ 12 ноября 2018

Если вы посмотрите на код клиентской библиотеки, то увидите, что объект ответа JSON RPC уже разобран, и либо при ошибке возвращается ошибка, либо анализируется фактический результат: https://github.com/ethereum/go-ethereum/blob/master/rpc/client.go#L277

Однако парсер уже развернул содержащее поле "result". Ваш тип все еще хочет сделать дополнительную развёртку:

type response struct {
    Result string
}

Удалите внешнюю структуру, просто передайте строковый указатель на первый параметр client.Call.

0 голосов
/ 10 ноября 2018

В вашей структуре ответа не отображаются данные, которые имеет json ответа

попробуйте это

type response struct {
    Jsonrpc string `json:"jsonrpc"`
    ID      int    `json:"id"`
    Result  string `json:"result"`
}
...