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  }