decred.org/dcrwallet/v3@v3.1.0/rpc/client/dcrd/json.go (about) 1 // Copyright (c) 2019 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package dcrd 6 7 import ( 8 "bytes" 9 "encoding/hex" 10 "encoding/json" 11 "io" 12 "strings" 13 14 "decred.org/dcrwallet/v3/errors" 15 "github.com/decred/dcrd/chaincfg/chainhash" 16 "github.com/decred/dcrd/gcs/v4" 17 blockcf "github.com/decred/dcrd/gcs/v4/blockcf2" 18 "github.com/decred/dcrd/wire" 19 ) 20 21 type deserializer interface { 22 Deserialize(r io.Reader) error 23 } 24 25 type unmarshalFunc func(j []byte) error 26 27 func (f *unmarshalFunc) UnmarshalJSON(j []byte) error { 28 return (*f)(j) 29 } 30 31 // unhex returns a json.Unmarshaler which unmarshals a hex-encoded wire message. 32 func unhex(msg deserializer) json.Unmarshaler { 33 f := func(j []byte) error { 34 if len(j) < 2 || j[0] != '"' || j[len(j)-1] != '"' { 35 return errors.E(errors.Encoding, "not a string") 36 } 37 err := msg.Deserialize(hex.NewDecoder(bytes.NewReader(j[1 : len(j)-1]))) 38 if err != nil { 39 return errors.E(errors.Encoding, err) 40 } 41 return nil 42 } 43 return (*unmarshalFunc)(&f) 44 } 45 46 // cfilterV2 implements deserializer to read a version 2 committed filter from 47 // a io.Reader. Filters are assumed to be serialized as <n filter> with 48 // consensus-determined B and M values. 49 // 50 // Note that this is only the deserializer for the raw filter data and *not* 51 // for the full response to a cfilterv2 call (see cfilterv2Reply for that). 52 type cfilterV2 struct { 53 Filter *gcs.FilterV2 54 } 55 56 func (f *cfilterV2) Deserialize(r io.Reader) error { 57 b, err := io.ReadAll(r) 58 if err != nil { 59 return err 60 } 61 f.Filter, err = gcs.FromBytesV2(blockcf.B, blockcf.M, b) 62 return err 63 } 64 65 func (f *cfilterV2) UnmarshalJSON(j []byte) error { 66 if len(j)&1 == 1 || j[0] != '"' || j[len(j)-1] != '"' { 67 return errors.E(errors.Encoding, "cfilterv2 is not an even hex string") 68 } 69 70 b := make([]byte, len(j)/2-1) 71 _, err := hex.Decode(b, j[1:len(j)-1]) 72 if err != nil { 73 return errors.E(errors.Encoding, err) 74 } 75 76 f.Filter, err = gcs.FromBytesV2(blockcf.B, blockcf.M, b) 77 return err 78 } 79 80 // cfilterv2Reply implements the reply to a cfilterv2 query to a dcrd rpc 81 // server. 82 type cfilterV2Reply struct { 83 Filter *cfilterV2 `json:"data"` 84 ProofIndex uint32 `json:"proofindex"` 85 ProofHashes *hashes `json:"proofhashes"` 86 } 87 88 // hashes converts the internal []*chainhash.Hash to a []chainhash.Hash used by 89 // inclusion proofs. 90 func (r cfilterV2Reply) proofHashes() []chainhash.Hash { 91 if r.ProofHashes == nil { 92 return nil 93 } 94 h := make([]chainhash.Hash, len(r.ProofHashes.Hashes)) 95 for i, hp := range r.ProofHashes.Hashes { 96 h[i] = *hp 97 } 98 return h 99 } 100 101 // hash implements json.Unmarshaler to decode 32-byte reversed hex hashes. 102 type hash struct { 103 Hash *chainhash.Hash 104 } 105 106 func (h *hash) UnmarshalJSON(j []byte) error { 107 if len(j) != 66 || j[0] != '"' || j[len(j)-1] != '"' { 108 return errors.E(errors.Encoding, "not a 32-byte hash hex string") 109 } 110 h.Hash = new(chainhash.Hash) 111 _, err := hex.Decode(h.Hash[:], j[1:len(j)-1]) 112 if err != nil { 113 return errors.E(errors.Encoding, err) 114 } 115 // Unreverse hash 116 for i, j := 0, len(h.Hash)-1; i < j; i, j = i+1, j-1 { 117 h.Hash[i], h.Hash[j] = h.Hash[j], h.Hash[i] 118 } 119 return nil 120 } 121 122 // hashes implements json.Marshaler/Unmarshaler to encode and decode slices of 123 // hashes as JSON arrays of reversed hex strings. 124 type hashes struct { 125 Hashes []*chainhash.Hash 126 } 127 128 func (h *hashes) UnmarshalJSON(j []byte) error { 129 if bytes.Equal(j, []byte("null")) { 130 h.Hashes = nil 131 return nil 132 } 133 var array []string 134 err := json.Unmarshal(j, &array) 135 if err != nil { 136 return nil 137 } 138 h.Hashes = make([]*chainhash.Hash, len(array)) 139 for i, s := range array { 140 hash, err := chainhash.NewHashFromStr(s) 141 if err != nil { 142 return errors.E(errors.Encoding, err) 143 } 144 h.Hashes[i] = hash 145 } 146 return nil 147 } 148 149 func (h *hashes) MarshalJSON() ([]byte, error) { 150 if h.Hashes == nil { 151 return []byte("null"), nil 152 } 153 buf := new(bytes.Buffer) 154 scratch32 := make([]byte, 32) 155 scratch64 := make([]byte, 64) 156 buf.Grow(2 + 67*len(h.Hashes)) // 2 for [], 64+2+1 per hash for strings, quotes, and separator 157 buf.WriteByte('[') 158 for i, h := range h.Hashes { 159 if i != 0 { 160 buf.WriteByte(',') 161 } 162 // Reverse hash into scratch space 163 for i := 0; i < 32; i++ { 164 scratch32[31-i] = h[i] 165 } 166 // Write hex encoding of reversed hash 167 hex.Encode(scratch64, scratch32) 168 buf.WriteByte('"') 169 buf.Write(scratch64) 170 buf.WriteByte('"') 171 } 172 buf.WriteByte(']') 173 return buf.Bytes(), nil 174 } 175 176 type hashesContiguous struct { 177 Hashes []chainhash.Hash 178 } 179 180 func (h *hashesContiguous) UnmarshalJSON(j []byte) error { 181 if bytes.Equal(j, []byte("null")) { 182 h.Hashes = nil 183 return nil 184 } 185 var array []string 186 err := json.Unmarshal(j, &array) 187 if err != nil { 188 return nil 189 } 190 h.Hashes = make([]chainhash.Hash, len(array)) 191 for i, s := range array { 192 hash, err := chainhash.NewHashFromStr(s) 193 if err != nil { 194 return errors.E(errors.Encoding, err) 195 } 196 h.Hashes[i] = *hash 197 } 198 return nil 199 } 200 201 func (h *hashesContiguous) MarshalJSON() ([]byte, error) { 202 if h.Hashes == nil { 203 return []byte("null"), nil 204 } 205 buf := new(bytes.Buffer) 206 scratch32 := make([]byte, 32) 207 scratch64 := make([]byte, 64) 208 buf.Grow(2 + 67*len(h.Hashes)) // 2 for [], 64+2+1 per hash for strings, quotes, and separator 209 buf.WriteByte('[') 210 for i, h := range h.Hashes { 211 if i != 0 { 212 buf.WriteByte(',') 213 } 214 // Reverse hash into scratch space 215 for i := 0; i < 32; i++ { 216 scratch32[31-i] = h[i] 217 } 218 // Write hex encoding of reversed hash 219 hex.Encode(scratch64, scratch32) 220 buf.WriteByte('"') 221 buf.Write(scratch64) 222 buf.WriteByte('"') 223 } 224 buf.WriteByte(']') 225 return buf.Bytes(), nil 226 } 227 228 // headers implements json.Unmarshaler to decode JSON arrays of hex-encoded 229 // serialized block headers. 230 type headers struct { 231 Headers []*wire.BlockHeader 232 } 233 234 func (h *headers) UnmarshalJSON(j []byte) error { 235 if bytes.Equal(j, []byte("null")) { 236 h.Headers = nil 237 return nil 238 } 239 var array []string 240 err := json.Unmarshal(j, &array) 241 if err != nil { 242 return err 243 } 244 h.Headers = make([]*wire.BlockHeader, len(array)) 245 for i, s := range array { 246 h.Headers[i] = new(wire.BlockHeader) 247 err = h.Headers[i].Deserialize(hex.NewDecoder(strings.NewReader(s))) 248 if err != nil { 249 return errors.E(errors.Encoding, err) 250 } 251 } 252 return nil 253 } 254 255 type transactions struct { 256 Transactions []*wire.MsgTx 257 } 258 259 func (t *transactions) UnmarshalJSON(j []byte) error { 260 if bytes.Equal(j, []byte("null")) { 261 t.Transactions = nil 262 return nil 263 } 264 var array []json.RawMessage 265 err := json.Unmarshal(j, &array) 266 if err != nil { 267 return err 268 } 269 t.Transactions = make([]*wire.MsgTx, len(array)) 270 for i, j := range array { 271 if len(j) < 2 || j[0] != '"' || j[len(j)-1] != '"' { 272 return errors.E(errors.Encoding, "not a string") 273 } 274 t.Transactions[i] = new(wire.MsgTx) 275 err = t.Transactions[i].Deserialize(hex.NewDecoder(bytes.NewReader(j[1 : len(j)-1]))) 276 if err != nil { 277 return errors.E(errors.Encoding, err) 278 } 279 } 280 return nil 281 }