forked from 0xPolygon/polygon-edge
/
codec.go
212 lines (171 loc) · 4.95 KB
/
codec.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
package jsonrpc
import (
"encoding/json"
"fmt"
"strings"
"github.com/Gabulhas/polygon-external-consensus/types"
)
// Request is a jsonrpc request
type Request struct {
ID interface{} `json:"id"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
// Response is a jsonrpc response interface
type Response interface {
GetID() interface{}
Data() json.RawMessage
Bytes() ([]byte, error)
}
// ErrorResponse is a jsonrpc error response
type ErrorResponse struct {
JSONRPC string `json:"jsonrpc"`
ID interface{} `json:"id,omitempty"`
Error *ObjectError `json:"error"`
}
// GetID returns error response id
func (e *ErrorResponse) GetID() interface{} {
return e.ID
}
// Data returns ObjectError
func (e *ErrorResponse) Data() json.RawMessage {
data, err := json.Marshal(e.Error)
if err != nil {
return json.RawMessage(err.Error())
}
return data
}
// Bytes return the serialized response
func (e *ErrorResponse) Bytes() ([]byte, error) {
return json.Marshal(e)
}
// SuccessResponse is a jsonrpc success response
type SuccessResponse struct {
JSONRPC string `json:"jsonrpc"`
ID interface{} `json:"id"`
Result json.RawMessage `json:"result"`
Error *ObjectError `json:"error,omitempty"`
}
// GetID returns success response id
func (s *SuccessResponse) GetID() interface{} {
return s.ID
}
// Data returns the result
func (s *SuccessResponse) Data() json.RawMessage {
if s.Result != nil {
return s.Result
}
return json.RawMessage("No Data")
}
// Bytes return the serialized response
func (s *SuccessResponse) Bytes() ([]byte, error) {
return json.Marshal(s)
}
// ObjectError is a jsonrpc error
type ObjectError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
// Error implements error interface
func (e *ObjectError) Error() string {
data, err := json.Marshal(e)
if err != nil {
return fmt.Sprintf("jsonrpc.internal marshal error: %v", err)
}
return string(data)
}
const (
PendingBlockNumber = BlockNumber(-3)
LatestBlockNumber = BlockNumber(-2)
EarliestBlockNumber = BlockNumber(-1)
)
type BlockNumber int64
type BlockNumberOrHash struct {
BlockNumber *BlockNumber `json:"blockNumber,omitempty"`
BlockHash *types.Hash `json:"blockHash,omitempty"`
}
// UnmarshalJSON will try to extract the filter's data.
// Here are the possible input formats :
//
// 1 - "latest", "pending" or "earliest" - self-explaining keywords
// 2 - "0x2" - block number #2 (EIP-1898 backward compatible)
// 3 - {blockNumber: "0x2"} - EIP-1898 compliant block number #2
// 4 - {blockHash: "0xe0e..."} - EIP-1898 compliant block hash 0xe0e...
func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
type bnhCopy BlockNumberOrHash
var placeholder bnhCopy
err := json.Unmarshal(data, &placeholder)
if err != nil {
number, err := stringToBlockNumber(string(data))
if err != nil {
return err
}
placeholder.BlockNumber = &number
}
// Try to extract object
bnh.BlockNumber = placeholder.BlockNumber
bnh.BlockHash = placeholder.BlockHash
if bnh.BlockNumber != nil && bnh.BlockHash != nil {
return fmt.Errorf("cannot use both block number and block hash as filters")
} else if bnh.BlockNumber == nil && bnh.BlockHash == nil {
return fmt.Errorf("block number and block hash are empty, please provide one of them")
}
return nil
}
func stringToBlockNumber(str string) (BlockNumber, error) {
if str == "" {
return 0, fmt.Errorf("value is empty")
}
str = strings.Trim(str, "\"")
switch str {
case "pending":
return PendingBlockNumber, nil
case "latest":
return LatestBlockNumber, nil
case "earliest":
return EarliestBlockNumber, nil
}
n, err := types.ParseUint64orHex(&str)
if err != nil {
return 0, err
}
return BlockNumber(n), nil
}
func createBlockNumberPointer(str string) (*BlockNumber, error) {
blockNumber, err := stringToBlockNumber(str)
if err != nil {
return nil, err
}
return &blockNumber, nil
}
// UnmarshalJSON automatically decodes the user input for the block number, when a JSON RPC method is called
func (b *BlockNumber) UnmarshalJSON(buffer []byte) error {
num, err := stringToBlockNumber(string(buffer))
if err != nil {
return err
}
*b = num
return nil
}
// NewRPCErrorResponse is used to create a custom error response
func NewRPCErrorResponse(id interface{}, errCode int, err string, jsonrpcver string) Response {
errObject := &ObjectError{errCode, err, nil}
response := &ErrorResponse{
JSONRPC: jsonrpcver,
ID: id,
Error: errObject,
}
return response
}
// NewRPCResponse returns Success/Error response object
func NewRPCResponse(id interface{}, jsonrpcver string, reply []byte, err Error) Response {
var response Response
switch err.(type) {
case nil:
response = &SuccessResponse{JSONRPC: jsonrpcver, ID: id, Result: reply}
default:
response = NewRPCErrorResponse(id, err.ErrorCode(), err.Error(), jsonrpcver)
}
return response
}