如何使用 Golang 正确发送 RPC 调用以获取智能合约所有者?
Posted
技术标签:
【中文标题】如何使用 Golang 正确发送 RPC 调用以获取智能合约所有者?【英文标题】:How to correctly send RPC call using Golang to get smart-contract owner? 【发布时间】:2018-11-10 09:47:39 【问题描述】:更新
由于我无法使用此问题中的方法来实现这一点,因此我创建了自己的库来做同样的事情 (link)。它不依赖 go-ethereum 包,而是使用普通的net/http
包来做 JSON RPC 请求。
我仍然很想知道我在下面的方法中做错了什么。
定义:
所有者 =public
与address
类型的合同变量
contract = 拥有owner的智能合约
这是获取合约所有者的 curl 请求。我设法得到了主人。 (JSON RPC docs)
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: cannot unmarshal string into Go value of type main.response 错误。 (go-ethereum code that I use)
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 方法的情况下解决这个特定问题。
【问题讨论】:
【参考方案1】:您可以使用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())
【讨论】:
谢谢。这是最接近的解决方案。感谢您的帮助!【参考方案2】:如果您查看客户端库代码,您会看到 JSON RPC 响应对象已经被反汇编,并且失败时返回错误,或者解析出的实际结果:https://github.com/ethereum/go-ethereum/blob/master/rpc/client.go#L277
然而,解析器已经解开了包含“结果”字段。你的类型仍然想做一个额外的解包:
type response struct
Result string
删除外部结构,只需将字符串指针传递给client.Call
的第一个参数。
【讨论】:
对不起@Péter Szilágyi,我不是很清楚。你能在代码中显示它吗?谢谢。【参考方案3】:您的响应结构没有显示响应的 json 具有的数据
试试这个
type response struct
Jsonrpc string `json:"jsonrpc"`
ID int `json:"id"`
Result string `json:"result"`
【讨论】:
感谢您的帮助。不幸的是,我仍然收到json: cannot unmarshal string into Go value of type main.response
错误。
尝试调整响应。我没有查看您正在使用的库,它可能会剥离 jsonrpc 或 id
我试过了。我评论了Jsonrpc
。它失败了。接下来我取消了Jsonrpc
的注释并评论了ID
。还是失败了。
在 go-ethereum client.go 的第 277 行添加到 printf("%v",resp.Result)
,就在它触发错误之前。看看它返回了什么【参考方案4】:
json: cannot unmarshal string into Go value of type main.response 错误。我在解组响应时遇到了类似的类型错误。这是因为响应实际上是 json 字符串,我的意思是它有引号 "
作为第一个字符。所以为了确保你也遇到了同样的问题,请printf("%v",resp.Result)
在这里解组之前https://github.com/ethereum/go-ethereum/blob/1ff152f3a43e4adf030ac61eb5d8da345554fc5a/rpc/client.go#L278。
【讨论】:
以上是关于如何使用 Golang 正确发送 RPC 调用以获取智能合约所有者?的主要内容,如果未能解决你的问题,请参考以下文章
Rabbit MQ 阻止调用以发送消息并确保它为超出消息限制或超出消息大小限制提供正确的回复代码