github.com/jincm/wesharechain@v0.0.0-20210122032815-1537409ce26a/chain/swarm/pss/api.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  	"context"
    21  	"errors"
    22  	"fmt"
    23  
    24  	"github.com/ethereum/go-ethereum/common/hexutil"
    25  	"github.com/ethereum/go-ethereum/crypto"
    26  	"github.com/ethereum/go-ethereum/p2p"
    27  	"github.com/ethereum/go-ethereum/rpc"
    28  	"github.com/ethereum/go-ethereum/swarm/log"
    29  )
    30  
    31  // Wrapper for receiving pss messages when using the pss API
    32  // providing access to sender of message
    33  type APIMsg struct {
    34  	Msg        hexutil.Bytes
    35  	Asymmetric bool
    36  	Key        string
    37  }
    38  
    39  // Additional public methods accessible through API for pss
    40  type API struct {
    41  	*Pss
    42  }
    43  
    44  func NewAPI(ps *Pss) *API {
    45  	return &API{Pss: ps}
    46  }
    47  
    48  // Creates a new subscription for the caller. Enables external handling of incoming messages.
    49  //
    50  // A new handler is registered in pss for the supplied topic
    51  //
    52  // All incoming messages to the node matching this topic will be encapsulated in the APIMsg
    53  // struct and sent to the subscriber
    54  func (pssapi *API) Receive(ctx context.Context, topic Topic, raw bool, prox bool) (*rpc.Subscription, error) {
    55  	notifier, supported := rpc.NotifierFromContext(ctx)
    56  	if !supported {
    57  		return nil, fmt.Errorf("Subscribe not supported")
    58  	}
    59  
    60  	psssub := notifier.CreateSubscription()
    61  
    62  	hndlr := NewHandler(func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
    63  		apimsg := &APIMsg{
    64  			Msg:        hexutil.Bytes(msg),
    65  			Asymmetric: asymmetric,
    66  			Key:        keyid,
    67  		}
    68  		if err := notifier.Notify(psssub.ID, apimsg); err != nil {
    69  			log.Warn(fmt.Sprintf("notification on pss sub topic rpc (sub %v) msg %v failed!", psssub.ID, msg))
    70  		}
    71  		return nil
    72  	})
    73  	if raw {
    74  		hndlr.caps.raw = true
    75  	}
    76  	if prox {
    77  		hndlr.caps.prox = true
    78  	}
    79  
    80  	deregf := pssapi.Register(&topic, hndlr)
    81  	go func() {
    82  		defer deregf()
    83  		select {
    84  		case err := <-psssub.Err():
    85  			log.Warn(fmt.Sprintf("caught subscription error in pss sub topic %x: %v", topic, err))
    86  		case <-notifier.Closed():
    87  			log.Warn(fmt.Sprintf("rpc sub notifier closed"))
    88  		}
    89  	}()
    90  
    91  	return psssub, nil
    92  }
    93  
    94  func (pssapi *API) GetAddress(topic Topic, asymmetric bool, key string) (PssAddress, error) {
    95  	var addr PssAddress
    96  	if asymmetric {
    97  		peer, ok := pssapi.Pss.pubKeyPool[key][topic]
    98  		if !ok {
    99  			return nil, fmt.Errorf("pubkey/topic pair %x/%x doesn't exist", key, topic)
   100  		}
   101  		addr = peer.address
   102  	} else {
   103  		peer, ok := pssapi.Pss.symKeyPool[key][topic]
   104  		if !ok {
   105  			return nil, fmt.Errorf("symkey/topic pair %x/%x doesn't exist", key, topic)
   106  		}
   107  		addr = peer.address
   108  
   109  	}
   110  	return addr, nil
   111  }
   112  
   113  // Retrieves the node's base address in hex form
   114  func (pssapi *API) BaseAddr() (PssAddress, error) {
   115  	return PssAddress(pssapi.Pss.BaseAddr()), nil
   116  }
   117  
   118  // Retrieves the node's public key in hex form
   119  func (pssapi *API) GetPublicKey() (keybytes hexutil.Bytes) {
   120  	key := pssapi.Pss.PublicKey()
   121  	keybytes = crypto.FromECDSAPub(key)
   122  	return keybytes
   123  }
   124  
   125  // Set Public key to associate with a particular Pss peer
   126  func (pssapi *API) SetPeerPublicKey(pubkey hexutil.Bytes, topic Topic, addr PssAddress) error {
   127  	pk, err := crypto.UnmarshalPubkey(pubkey)
   128  	if err != nil {
   129  		return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkey)
   130  	}
   131  	err = pssapi.Pss.SetPeerPublicKey(pk, topic, addr)
   132  	if err != nil {
   133  		return fmt.Errorf("Invalid key: %x", pk)
   134  	}
   135  	return nil
   136  }
   137  
   138  func (pssapi *API) GetSymmetricKey(symkeyid string) (hexutil.Bytes, error) {
   139  	symkey, err := pssapi.Pss.GetSymmetricKey(symkeyid)
   140  	return hexutil.Bytes(symkey), err
   141  }
   142  
   143  func (pssapi *API) GetSymmetricAddressHint(topic Topic, symkeyid string) (PssAddress, error) {
   144  	return pssapi.Pss.symKeyPool[symkeyid][topic].address, nil
   145  }
   146  
   147  func (pssapi *API) GetAsymmetricAddressHint(topic Topic, pubkeyid string) (PssAddress, error) {
   148  	return pssapi.Pss.pubKeyPool[pubkeyid][topic].address, nil
   149  }
   150  
   151  func (pssapi *API) StringToTopic(topicstring string) (Topic, error) {
   152  	topicbytes := BytesToTopic([]byte(topicstring))
   153  	if topicbytes == rawTopic {
   154  		return rawTopic, errors.New("Topic string hashes to 0x00000000 and cannot be used")
   155  	}
   156  	return topicbytes, nil
   157  }
   158  
   159  func (pssapi *API) SendAsym(pubkeyhex string, topic Topic, msg hexutil.Bytes) error {
   160  	if err := validateMsg(msg); err != nil {
   161  		return err
   162  	}
   163  	return pssapi.Pss.SendAsym(pubkeyhex, topic, msg[:])
   164  }
   165  
   166  func (pssapi *API) SendSym(symkeyhex string, topic Topic, msg hexutil.Bytes) error {
   167  	if err := validateMsg(msg); err != nil {
   168  		return err
   169  	}
   170  	return pssapi.Pss.SendSym(symkeyhex, topic, msg[:])
   171  }
   172  
   173  func (pssapi *API) SendRaw(addr hexutil.Bytes, topic Topic, msg hexutil.Bytes) error {
   174  	if err := validateMsg(msg); err != nil {
   175  		return err
   176  	}
   177  	return pssapi.Pss.SendRaw(PssAddress(addr), topic, msg[:])
   178  }
   179  
   180  func (pssapi *API) GetPeerTopics(pubkeyhex string) ([]Topic, error) {
   181  	topics, _, err := pssapi.Pss.GetPublickeyPeers(pubkeyhex)
   182  	return topics, err
   183  
   184  }
   185  
   186  func (pssapi *API) GetPeerAddress(pubkeyhex string, topic Topic) (PssAddress, error) {
   187  	return pssapi.Pss.getPeerAddress(pubkeyhex, topic)
   188  }
   189  
   190  func validateMsg(msg []byte) error {
   191  	if len(msg) == 0 {
   192  		return errors.New("invalid message length")
   193  	}
   194  	return nil
   195  }