Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebase polymer develop to match v0.0.24 #2

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ setup:
run:
@go run ./cmd/erpc/main.go

.PHONY: run-pprof
run-pprof:
@go run ./cmd/erpc/main.go ./cmd/erpc/pprof.go

.PHONY: run-fake-rpcs
run-fake-rpcs:
@go run ./test/cmd/main.go
Expand Down
3 changes: 3 additions & 0 deletions cmd/erpc/pprof.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ package main
import (
"net/http"
_ "net/http/pprof"
"runtime"

"github.com/rs/zerolog/log"
)

func init() {
go func() {
runtime.SetMutexProfileFraction(1)
runtime.SetBlockProfileRate(1)
log.Info().Msgf("pprof server started at http://localhost:6060")
http.ListenAndServe("0.0.0.0:6060", nil)
}()
Expand Down
4 changes: 2 additions & 2 deletions common/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,11 +624,11 @@ var NewErrUpstreamsExhausted = func(
) error {
// TODO create a new error type that holds a map to avoid creating a new array
ers := []error{}
req.Mu.RLock()
req.RLock()
for _, err := range ersObj {
ers = append(ers, err)
}
req.Mu.RUnlock()
req.RUnlock()
e := &ErrUpstreamsExhausted{
BaseError{
Code: ErrCodeUpstreamsExhausted,
Expand Down
8 changes: 7 additions & 1 deletion common/evm_block_ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func ExtractEvmBlockReferenceFromRequest(r *JsonRpcRequest) (string, int64, erro
return "", 0, errors.New("cannot extract block reference when json-rpc request is nil")
}

r.RLock()
defer r.RUnlock()

switch r.Method {
case "eth_getBlockByNumber",
"eth_getUncleByBlockNumberAndIndex",
Expand Down Expand Up @@ -166,6 +169,8 @@ func ExtractEvmBlockReferenceFromResponse(rpcReq *JsonRpcRequest, rpcResp *JsonR
if err != nil {
return "", 0, err
}
rpcResp.RLock()
defer rpcResp.RUnlock()
if tx, ok := result.(map[string]interface{}); ok {
var blockRef string
var blockNumber int64
Expand All @@ -189,7 +194,8 @@ func ExtractEvmBlockReferenceFromResponse(rpcReq *JsonRpcRequest, rpcResp *JsonR
if err != nil {
return "", 0, err
}

rpcResp.RLock()
defer rpcResp.RUnlock()
if blk, ok := result.(map[string]interface{}); ok {
var blockRef string
var blockNumber int64
Expand Down
4 changes: 2 additions & 2 deletions common/evm_json_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
)

func NormalizeEvmHttpJsonRpc(nrq *NormalizedRequest, r *JsonRpcRequest) error {
nrq.Mu.Lock()
defer nrq.Mu.Unlock()
r.Lock()
defer r.Unlock()

switch r.Method {
case "eth_getBlockByNumber",
Expand Down
178 changes: 106 additions & 72 deletions common/json_rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,15 @@ import (
"log"
"sort"
"strings"
"sync"

"github.com/bytedance/sonic"
"github.com/rs/zerolog"
)

type JsonRpcRequest struct {
JSONRPC string `json:"jsonrpc,omitempty"`
ID interface{} `json:"id,omitempty"`
Method string `json:"method"`
Params []interface{} `json:"params"`
}

type JsonRpcResponse struct {
sync.RWMutex

JSONRPC string `json:"jsonrpc,omitempty"`
ID interface{} `json:"id,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
Expand All @@ -43,6 +39,17 @@ func NewJsonRpcResponse(id interface{}, result interface{}, rpcError *ErrJsonRpc
}

func (r *JsonRpcResponse) ParsedResult() (interface{}, error) {
r.RLock()
if r.parsedResult != nil {
defer r.RUnlock()
return r.parsedResult, nil
}
r.RUnlock()

r.Lock()
defer r.Unlock()

// Double-check in case another goroutine initialized it
if r.parsedResult != nil {
return r.parsedResult, nil
}
Expand All @@ -66,83 +73,28 @@ func (r *JsonRpcResponse) ParsedResult() (interface{}, error) {
return r.parsedResult, nil
}

func (r *JsonRpcRequest) MarshalZerologObject(e *zerolog.Event) {
func (r *JsonRpcResponse) MarshalZerologObject(e *zerolog.Event) {
if r == nil {
return
}
e.Str("method", r.Method).
Interface("params", r.Params).
Interface("id", r.ID)
}

func (r *JsonRpcRequest) CacheHash() (string, error) {
hasher := sha256.New()
r.Lock()
defer r.Unlock()

for _, p := range r.Params {
err := hashValue(hasher, p)
if err != nil {
return "", err
}
}

b := sha256.Sum256(hasher.Sum(nil))
return fmt.Sprintf("%s:%x", r.Method, b), nil
}

func hashValue(h io.Writer, v interface{}) error {
switch t := v.(type) {
case bool:
_, err := h.Write([]byte(fmt.Sprintf("%t", t)))
return err
case int:
_, err := h.Write([]byte(fmt.Sprintf("%d", t)))
return err
case float64:
_, err := h.Write([]byte(fmt.Sprintf("%f", t)))
return err
case string:
_, err := h.Write([]byte(strings.ToLower(t)))
return err
case []interface{}:
for _, i := range t {
err := hashValue(h, i)
if err != nil {
return err
}
}
return nil
case map[string]interface{}:
keys := make([]string, 0, len(t))
for k := range t {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if _, err := h.Write([]byte(k)); err != nil {
return err
}
err := hashValue(h, t[k])
if err != nil {
return err
}
}
return nil
default:
return fmt.Errorf("unsupported type for value during hash: %+v", v)
}
}

func (r *JsonRpcResponse) MarshalZerologObject(e *zerolog.Event) {
if r == nil {
return
}
e.Interface("id", r.ID).
Interface("result", r.Result).
Interface("error", r.Error)
}

// Custom unmarshal method for JsonRpcResponse
func (r *JsonRpcResponse) UnmarshalJSON(data []byte) error {
if r == nil {
return nil
}

r.Lock()
defer r.Unlock()

type Alias JsonRpcResponse
aux := &struct {
Error json.RawMessage `json:"error,omitempty"`
Expand Down Expand Up @@ -250,6 +202,88 @@ func (r *JsonRpcResponse) UnmarshalJSON(data []byte) error {
return nil
}

type JsonRpcRequest struct {
sync.RWMutex

JSONRPC string `json:"jsonrpc,omitempty"`
ID interface{} `json:"id,omitempty"`
Method string `json:"method"`
Params []interface{} `json:"params"`
}

func (r *JsonRpcRequest) MarshalZerologObject(e *zerolog.Event) {
if r == nil {
return
}
e.Str("method", r.Method).
Interface("params", r.Params).
Interface("id", r.ID)
}

func (r *JsonRpcRequest) CacheHash() (string, error) {
if r == nil {
return "", nil
}

r.RLock()
defer r.RUnlock()

hasher := sha256.New()

for _, p := range r.Params {
err := hashValue(hasher, p)
if err != nil {
return "", err
}
}

b := sha256.Sum256(hasher.Sum(nil))
return fmt.Sprintf("%s:%x", r.Method, b), nil
}

func hashValue(h io.Writer, v interface{}) error {
switch t := v.(type) {
case bool:
_, err := h.Write([]byte(fmt.Sprintf("%t", t)))
return err
case int:
_, err := h.Write([]byte(fmt.Sprintf("%d", t)))
return err
case float64:
_, err := h.Write([]byte(fmt.Sprintf("%f", t)))
return err
case string:
_, err := h.Write([]byte(strings.ToLower(t)))
return err
case []interface{}:
for _, i := range t {
err := hashValue(h, i)
if err != nil {
return err
}
}
return nil
case map[string]interface{}:
keys := make([]string, 0, len(t))
for k := range t {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
if _, err := h.Write([]byte(k)); err != nil {
return err
}
err := hashValue(h, t[k])
if err != nil {
return err
}
}
return nil
default:
return fmt.Errorf("unsupported type for value during hash: %+v", v)
}
}

// TranslateToJsonRpcException is mainly responsible to translate internal eRPC errors (not those coming from upstreams) to
// a proper json-rpc error with correct numeric code.
func TranslateToJsonRpcException(err error) error {
Expand Down
Loading
Loading