github.com/0chain/gosdk@v1.17.11/core/util/http_consensus_maps.go (about)

     1  package util
     2  
     3  import (
     4  	"crypto/sha1"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"net/http"
     9  	"sort"
    10  	"strings"
    11  )
    12  
    13  var ErrNilHttpConsensusMaps = errors.New("nil_httpconsensusmaps")
    14  
    15  type HttpConsensusMaps struct {
    16  	ConsensusThresh int
    17  	MaxConsensus    int
    18  
    19  	WinMap          map[string]json.RawMessage
    20  	WinMapConsensus map[string]int
    21  
    22  	WinError string
    23  	WinInfo  string
    24  }
    25  
    26  func NewHttpConsensusMaps(consensusThresh int) *HttpConsensusMaps {
    27  	return &HttpConsensusMaps{
    28  		ConsensusThresh: consensusThresh,
    29  		WinMapConsensus: make(map[string]int),
    30  	}
    31  }
    32  
    33  func (c *HttpConsensusMaps) GetValue(name string) (json.RawMessage, bool) {
    34  	if c == nil || c.WinMap == nil {
    35  		return nil, false
    36  	}
    37  	v, ok := c.WinMap[name]
    38  	return v, ok
    39  }
    40  
    41  func (c *HttpConsensusMaps) Add(statusCode int, respBody string) error {
    42  	if c == nil {
    43  		return ErrNilHttpConsensusMaps
    44  	}
    45  	if statusCode != http.StatusOK {
    46  		c.WinError = respBody
    47  		return nil
    48  	}
    49  
    50  	m, hash, err := c.buildMap(respBody)
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	c.WinMapConsensus[hash]++
    56  
    57  	if c.WinMapConsensus[hash] > c.MaxConsensus {
    58  		c.MaxConsensus = c.WinMapConsensus[hash]
    59  		c.WinMap = m
    60  		c.WinInfo = respBody
    61  	}
    62  
    63  	return nil
    64  }
    65  
    66  func (c *HttpConsensusMaps) buildMap(respBody string) (map[string]json.RawMessage, string, error) {
    67  	var m map[string]json.RawMessage
    68  	err := json.Unmarshal([]byte(respBody), &m)
    69  	if err != nil {
    70  		return nil, "", err
    71  	}
    72  
    73  	keys := make([]string, 0, len(m))
    74  
    75  	for k := range m {
    76  
    77  		keys = append(keys, k)
    78  	}
    79  	sort.Strings(keys)
    80  
    81  	sb := strings.Builder{}
    82  
    83  	for _, k := range keys {
    84  		sb.Write(m[k])
    85  		sb.WriteString(":")
    86  	}
    87  
    88  	h := sha1.New()
    89  	h.Write([]byte(sb.String()))
    90  	hash := h.Sum(nil)
    91  
    92  	return m, hex.EncodeToString(hash), nil
    93  }