github.com/jincm/wesharechain@v0.0.0-20210122032815-1537409ce26a/chain/swarm/pss/types.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package pss
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"sync"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/common/hexutil"
    26  	"github.com/ethereum/go-ethereum/p2p"
    27  	"github.com/ethereum/go-ethereum/rlp"
    28  	"github.com/ethereum/go-ethereum/swarm/storage"
    29  	whisper "github.com/ethereum/go-ethereum/whisper/whisperv6"
    30  )
    31  
    32  const (
    33  	defaultWhisperTTL = 6000
    34  )
    35  
    36  const (
    37  	pssControlSym = 1
    38  	pssControlRaw = 1 << 1
    39  )
    40  
    41  var (
    42  	topicHashMutex = sync.Mutex{}
    43  	topicHashFunc  = storage.MakeHashFunc("SHA256")()
    44  	rawTopic       = Topic{}
    45  )
    46  
    47  // Topic is the PSS encapsulation of the Whisper topic type
    48  type Topic whisper.TopicType
    49  
    50  func (t *Topic) String() string {
    51  	return hexutil.Encode(t[:])
    52  }
    53  
    54  // MarshalJSON implements the json.Marshaler interface
    55  func (t Topic) MarshalJSON() (b []byte, err error) {
    56  	return json.Marshal(t.String())
    57  }
    58  
    59  // MarshalJSON implements the json.Marshaler interface
    60  func (t *Topic) UnmarshalJSON(input []byte) error {
    61  	topicbytes, err := hexutil.Decode(string(input[1 : len(input)-1]))
    62  	if err != nil {
    63  		return err
    64  	}
    65  	copy(t[:], topicbytes)
    66  	return nil
    67  }
    68  
    69  // PssAddress is an alias for []byte. It represents a variable length address
    70  type PssAddress []byte
    71  
    72  // MarshalJSON implements the json.Marshaler interface
    73  func (a PssAddress) MarshalJSON() ([]byte, error) {
    74  	return json.Marshal(hexutil.Encode(a[:]))
    75  }
    76  
    77  // UnmarshalJSON implements the json.Marshaler interface
    78  func (a *PssAddress) UnmarshalJSON(input []byte) error {
    79  	b, err := hexutil.Decode(string(input[1 : len(input)-1]))
    80  	if err != nil {
    81  		return err
    82  	}
    83  	for _, bb := range b {
    84  		*a = append(*a, bb)
    85  	}
    86  	return nil
    87  }
    88  
    89  // holds the digest of a message used for caching
    90  type pssDigest [digestLength]byte
    91  
    92  // conceals bitwise operations on the control flags byte
    93  type msgParams struct {
    94  	raw bool
    95  	sym bool
    96  }
    97  
    98  func newMsgParamsFromBytes(paramBytes []byte) *msgParams {
    99  	if len(paramBytes) != 1 {
   100  		return nil
   101  	}
   102  	return &msgParams{
   103  		raw: paramBytes[0]&pssControlRaw > 0,
   104  		sym: paramBytes[0]&pssControlSym > 0,
   105  	}
   106  }
   107  
   108  func (m *msgParams) Bytes() (paramBytes []byte) {
   109  	var b byte
   110  	if m.raw {
   111  		b |= pssControlRaw
   112  	}
   113  	if m.sym {
   114  		b |= pssControlSym
   115  	}
   116  	paramBytes = append(paramBytes, b)
   117  	return paramBytes
   118  }
   119  
   120  // PssMsg encapsulates messages transported over pss.
   121  type PssMsg struct {
   122  	To      []byte
   123  	Control []byte
   124  	Expire  uint32
   125  	Payload *whisper.Envelope
   126  }
   127  
   128  func newPssMsg(param *msgParams) *PssMsg {
   129  	return &PssMsg{
   130  		Control: param.Bytes(),
   131  	}
   132  }
   133  
   134  // message is flagged as raw / external encryption
   135  func (msg *PssMsg) isRaw() bool {
   136  	return msg.Control[0]&pssControlRaw > 0
   137  }
   138  
   139  // message is flagged as symmetrically encrypted
   140  func (msg *PssMsg) isSym() bool {
   141  	return msg.Control[0]&pssControlSym > 0
   142  }
   143  
   144  // serializes the message for use in cache
   145  func (msg *PssMsg) serialize() []byte {
   146  	rlpdata, _ := rlp.EncodeToBytes(struct {
   147  		To      []byte
   148  		Payload *whisper.Envelope
   149  	}{
   150  		To:      msg.To,
   151  		Payload: msg.Payload,
   152  	})
   153  	return rlpdata
   154  }
   155  
   156  // String representation of PssMsg
   157  func (msg *PssMsg) String() string {
   158  	return fmt.Sprintf("PssMsg: Recipient: %x", common.ToHex(msg.To))
   159  }
   160  
   161  // Signature for a message handler function for a PssMsg
   162  // Implementations of this type are passed to Pss.Register together with a topic,
   163  type HandlerFunc func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error
   164  
   165  type handlerCaps struct {
   166  	raw  bool
   167  	prox bool
   168  }
   169  
   170  // Handler defines code to be executed upon reception of content.
   171  type handler struct {
   172  	f    HandlerFunc
   173  	caps *handlerCaps
   174  }
   175  
   176  // NewHandler returns a new message handler
   177  func NewHandler(f HandlerFunc) *handler {
   178  	return &handler{
   179  		f:    f,
   180  		caps: &handlerCaps{},
   181  	}
   182  }
   183  
   184  // WithRaw is a chainable method that allows raw messages to be handled.
   185  func (h *handler) WithRaw() *handler {
   186  	h.caps.raw = true
   187  	return h
   188  }
   189  
   190  // WithProxBin is a chainable method that allows sending messages with full addresses to neighbourhoods using the kademlia depth as reference
   191  func (h *handler) WithProxBin() *handler {
   192  	h.caps.prox = true
   193  	return h
   194  }
   195  
   196  // the stateStore handles saving and loading PSS peers and their corresponding keys
   197  // it is currently unimplemented
   198  type stateStore struct {
   199  	values map[string][]byte
   200  }
   201  
   202  func (store *stateStore) Load(key string) ([]byte, error) {
   203  	return nil, nil
   204  }
   205  
   206  func (store *stateStore) Save(key string, v []byte) error {
   207  	return nil
   208  }
   209  
   210  // BytesToTopic hashes an arbitrary length byte slice and truncates it to the length of a topic, using only the first bytes of the digest
   211  func BytesToTopic(b []byte) Topic {
   212  	topicHashMutex.Lock()
   213  	defer topicHashMutex.Unlock()
   214  	topicHashFunc.Reset()
   215  	topicHashFunc.Write(b)
   216  	return Topic(whisper.BytesToTopic(topicHashFunc.Sum(nil)))
   217  }