github.com/okex/exchain@v1.8.0/libs/tendermint/rpc/jsonrpc/client/decode.go (about) 1 package client 2 3 import ( 4 "encoding/json" 5 6 "github.com/pkg/errors" 7 8 amino "github.com/tendermint/go-amino" 9 10 types "github.com/okex/exchain/libs/tendermint/rpc/jsonrpc/types" 11 ) 12 13 func unmarshalResponseBytes( 14 cdc *amino.Codec, 15 responseBytes []byte, 16 expectedID types.JSONRPCIntID, 17 result interface{}, 18 ) (interface{}, error) { 19 20 // Read response. If rpc/core/types is imported, the result will unmarshal 21 // into the correct type. 22 response := &types.RPCResponse{} 23 if err := json.Unmarshal(responseBytes, response); err != nil { 24 return nil, errors.Wrap(err, "error unmarshalling") 25 } 26 27 if response.Error != nil { 28 return nil, response.Error 29 } 30 31 if err := validateAndVerifyID(response, expectedID); err != nil { 32 return nil, errors.Wrap(err, "wrong ID") 33 } 34 35 // Unmarshal the RawMessage into the result. 36 if err := cdc.UnmarshalJSON(response.Result, result); err != nil { 37 return nil, errors.Wrap(err, "error unmarshalling result") 38 } 39 40 return result, nil 41 } 42 43 func unmarshalResponseBytesArray( 44 cdc *amino.Codec, 45 responseBytes []byte, 46 expectedIDs []types.JSONRPCIntID, 47 results []interface{}, 48 ) ([]interface{}, error) { 49 50 var ( 51 responses []types.RPCResponse 52 ) 53 54 if err := json.Unmarshal(responseBytes, &responses); err != nil { 55 return nil, errors.Wrap(err, "error unmarshalling") 56 } 57 58 // No response error checking here as there may be a mixture of successful 59 // and unsuccessful responses. 60 61 if len(results) != len(responses) { 62 return nil, errors.Errorf( 63 "expected %d result objects into which to inject responses, but got %d", 64 len(responses), 65 len(results), 66 ) 67 } 68 69 // Intersect IDs from responses with expectedIDs. 70 ids := make([]types.JSONRPCIntID, len(responses)) 71 var ok bool 72 for i, resp := range responses { 73 ids[i], ok = resp.ID.(types.JSONRPCIntID) 74 if !ok { 75 return nil, errors.Errorf("expected JSONRPCIntID, got %T", resp.ID) 76 } 77 } 78 if err := validateResponseIDs(ids, expectedIDs); err != nil { 79 return nil, errors.Wrap(err, "wrong IDs") 80 } 81 82 for i := 0; i < len(responses); i++ { 83 if err := cdc.UnmarshalJSON(responses[i].Result, results[i]); err != nil { 84 return nil, errors.Wrapf(err, "error unmarshalling #%d result", i) 85 } 86 } 87 88 return results, nil 89 } 90 91 func validateResponseIDs(ids, expectedIDs []types.JSONRPCIntID) error { 92 m := make(map[types.JSONRPCIntID]bool, len(expectedIDs)) 93 for _, expectedID := range expectedIDs { 94 m[expectedID] = true 95 } 96 97 for i, id := range ids { 98 if m[id] { 99 delete(m, id) 100 } else { 101 return errors.Errorf("unsolicited ID #%d: %v", i, id) 102 } 103 } 104 105 return nil 106 } 107 108 // From the JSON-RPC 2.0 spec: 109 // id: It MUST be the same as the value of the id member in the Request Object. 110 func validateAndVerifyID(res *types.RPCResponse, expectedID types.JSONRPCIntID) error { 111 if err := validateResponseID(res.ID); err != nil { 112 return err 113 } 114 if expectedID != res.ID.(types.JSONRPCIntID) { // validateResponseID ensured res.ID has the right type 115 return errors.Errorf("response ID (%d) does not match request ID (%d)", res.ID, expectedID) 116 } 117 return nil 118 } 119 120 func validateResponseID(id interface{}) error { 121 if id == nil { 122 return errors.New("no ID") 123 } 124 _, ok := id.(types.JSONRPCIntID) 125 if !ok { 126 return errors.Errorf("expected JSONRPCIntID, but got: %T", id) 127 } 128 return nil 129 }