首页天道酬勤eth改算法,java实现rpc调用

eth改算法,java实现rpc调用

张世龙 05-13 12:02 56次浏览

以太网提供RPC服务,可以在geth启动时通过参数进行设定

geth启动可选参数

--rpc启动HTTP-RPC服务(基于HTTP )

-ws启动WS-RPC服务(基于web服务)

--rpcapi value指定必须调用的HTTP-RPC API接口。 默认值只有eth、net和web3

--rpcport value HTTP-RPC服务器监听端口(default: 8545 ) ) ) )。

--rpcport value HTTP-RPC服务器监听端口(default: 8545 ) ) ) )。

示例: geth----RPC----RPCAPI'db,eth,net,web3,personal '

执行RPC调用的缺点是使用web3提供的接口、直接发送Json请求、使用go-ether eum/eth客户端包提供的函数,或者只有eth接口。 此外,还可以自己定义和调用接口。 以下代码示例使用go-ether eum/eth客户端包中的函数。

包主

导入(

' fmt '

' github.com/ether eum/go-ether eum/mobile '

func main () }

//NewEthereumClient函数只是创建EthereumClient结构并设置HTTP连接(如head )的某些参数的属性,而不是节点建立连接

cli,err :=geth.newethereumclient (' http://127.0.0.133608545 ) ) ) )

if err!=nil {

fmt.printf (createnewethereumrpcclienterr : % s\n ',err.Error ()

} else {

fmt.println (createnewethereumrpcclientsuccess ) )

}

eth_ctx :=geth.NewContext (

block,err 2:=CLI.getblockbynumber (eth _ CTX,18 ) ) ) ) ) ) )。

(fmt.printf (以太网mobilecontext : % v\n ),eth_ctx () ) ) ) ) ) 65

if err2!=nil {

fmt.printf (getblockerr : % s\n ),err2.Error ) )

} else {

FMT.printf('block:%v(n ),block () ) ) ) ) ) ) ) 652

}

}

的节点是本地运行的专用链,它将一些日志添加到go-ethereum源代码中并运行结果。

mylog : dial context : u : { scheme : http opaque : user : host :127.0.0.1:8545 path : raw path 3: foof

mylog:u.Scheme:http

createnewethereumrpcclientsuccess

mylog : JSON-RPC : clientcallcontext

mylog : client.is http 3360 true

ethereummobilecontext : { context :0 xc 4200 a c008 cancel : }

块:块(#18 ) : Size: 650.00 B {

miner hash : FD 55 c 05 AE 10a 5b 0159 b 3c 2d 5803 c 6a a 9469 c 95 F5 f 063 B9 c 400 a 2c 36 b 49616 ab 3

header (84 B2 CFD 65e 3197 bdfe 3f 748 ECE bb 040953 a F5 EB 73 a 05 d 8595757 cf 42 CB 40 a 492 ) :

[

parent hash :7892 a0b 31 d 50d 67 AE 20 d 4a 7e C5 c 24 a6 Fe 85 f2f 264 e9f 1639 aa 2388081305 a0BD

uncle hash :1 DCC 4d E8 dec 75 D7 aab 85 b 567 b6CCD 41 ad 312451 b 948 a 7413 f 0a 142 FD 40 d 49347

coin base : BDC 61 c 81f 67983288 a6 c 375 a 884661 EDC 77286 d 0

root :0 f 30637 bfc 5b D6 e 123 c 6a0c 38 BDC 743 c 94050626 a 984 f 9943 EAF 38367100 B3 e 3

tx sha 354 d 185 CFA 88 e 50 f1 a 425 e 5b 89500122 e 4445 e 9e c 737 e 7a 18c DD 61b 9350 ab 72 b

receipts ha : a 769 d 28981014 FB 60954

62148a6300cd0b43fa050d75eb6f5b7595cfd13136bb

Bloom: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Difficulty: 131072

Number: 18

GasLimit: 131877941

GasUsed: 21000

Time: 1527044372

Extra: ׃��geth�go1.10�darwin

MixDigest: 70c2bb422b1b834d5173d279e508ffee9dada454650fc3cf63e95deb3073cf32

Nonce: 58b7495f112ccac2

]

Transactions:

[

TX(57a3b17f84358098b728fc0f70f0697f175f8ba00d386c88eac0815b3afd6aad)

Contract: false

From: 2154bdd7070c99d1a25ff589a08b01dfd6eb65de

To: bdc61c81f67983288a6c375a884661edc77286d0

Nonce: 0

GasPrice: 0x430e23400

GasLimit 0x15f90

Value: 0xde0b6b3a7640000

Data: 0x

V: 0x41

R: 0x45d4952c0190373c56e62ad15e54db54c0246385371b23c70bab4126b51927f8

S: 0x618e4bb76a36482254352d7e5096c0dff4c1f495218d57c874fc3d8153915ea4

Hex: f86d80850430e2340083015f9094bdc61c81f67983288a6c375a884661edc77286d0880de0b6b3a76400008041a045d4952c0190373c56e62ad15e54db54c0246385371b23c70bab4126b51927f8a0618e4bb76a36482254352d7e5096c0dff4c1f495218d57c874fc3d8153915ea4

]

Uncles:

[]

}

分析:

go-ethereum/mobile包是发起RPC请求的客户端直接使用的包。

该包中有EthereumClient结构提供了Ethereum API的接入。

// EthereumClient provides access to the Ethereum APIs.

type EthereumClient struct {

client *ethclient.Client

}

ethclient.Client在ethclient包中,包装了rpc.Client,rpc.Client代表与RPC服务的一个连接。

// Client defines typed wrappers for the Ethereum RPC API.

type Client struct {

c *rpc.Client

}

RPC请求客户端在使用时,首先传入想要接入的节点的url作为参数,调用mobile包中的NewEthereumClient函数。创建了EthereumClient实例,并与节点建立连接。建立的RPC连接有三种形式:HTTP、WebSocket、IPC,当传入http://127.0.0.1:8545时,建立的是HTTP连接。

// NewEthereumClient connects a client to the given URL.

func NewEthereumClient(rawurl string) (client *EthereumClient, _ error) {

rawClient, err := ethclient.Dial(rawurl)

return &EthereumClient{rawClient}, err

}

设置HTTP连接的参数会调用rpc包http.go文件中的DialHTTPWithClient函数。

// DialHTTPWithClient creates a new RPC client that connects to an RPC server over HTTP

// using the provided HTTP Client.

func DialHTTPWithClient(endpoint string, client *http.Client) (*Client, error) {

req, err := http.NewRequest(http.MethodPost, endpoint, nil)

if err != nil {

return nil, err

}

// Content-Type和Accept是application/json,即发送的数据类型和接收的数据类型都是json

req.Header.Set("Content-Type", contentType)

req.Header.Set("Accept", contentType)

initctx := context.Background()

return newClient(initctx, func(context.Context) (net.Conn, error) {

return &httpConn{client: client, req: req, closed: make(chan struct{})}, nil

})

}

通过HTTP来做JSON-RPC调用时,需要一个geth.Context实例,通过调用mobile包中的NewContext函数,创建一个空的geth.Context实例。

// NewContext returns a non-nil, empty Context. It is never canceled, has no

// values, and has no deadline. It is typically used by the main function,

// initialization, and tests, and as the top-level Context for incoming requests.

func NewContext() *Context {

return &Context{

context: context.Background(),

}

}

mobile包中封装了请求区块、区块头、交易等函数,这些函数调用ethclient包中的相关函数,再调用更底层rpc包中封装的函数。

即mobile包-->ethclient包-->rpc包。如mobile包中根据区块号查找区块的函数最后会调用rpc包中的CallContext函数。

// CallContext扮演JSON-RPC调用角色

// CallContext performs a JSON-RPC call with the given arguments. If the context is

// canceled before the call has successfully returned, CallContext returns immediately.

//

// The result must be a pointer so that package json can unmarshal into it. You

// can also pass nil, in which case the result is ignored.

func (c *Client) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error {

fmt.Printf("mylog:JSON-RPC: Client CallContext\n")

msg, err := c.newMessage(method, args...)

if err != nil {

return err

}

op := &requestOp{ids: []json.RawMessage{msg.ID}, resp: make(chan *jsonrpcMessage, 1)}

fmt.Printf("mylog:Client.isHTTP:%+v\n",c.isHTTP)

if c.isHTTP {

err = c.sendHTTP(ctx, op, msg)

} else {

err = c.send(ctx, op, msg)

}

if err != nil {

return err

}

// dispatch has accepted the request and will close the channel it when it quits.

switch resp, err := op.wait(ctx); {

case err != nil:

return err

case resp.Error != nil:

return resp.Error

case len(resp.Result) == 0:

return ErrNoResult

default:

return json.Unmarshal(resp.Result, &result)

}

}

使用POSTMAN

使用POSTMAN发送请求时,注意设置下Content-type和Accept。

body是{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":67}

这种方式虽然直接,但是自己拼json会很麻烦,所以最方便的还是调用已有的接口。

使用POSTMAN

如果是做查询区块号为18的区块,则body是

{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x12",true],"id":1}

为什么要用rabbitmq,springboot netty ,