github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/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) (*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  	handler := 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  
    74  	deregf := pssapi.Register(&topic, handler)
    75  	go func() {
    76  		defer deregf()
    77  		select {
    78  		case err := <-psssub.Err():
    79  			log.Warn(fmt.Sprintf("caught subscription error in pss sub topic %x: %v", topic, err))
    80  		case <-notifier.Closed():
    81  			log.Warn(fmt.Sprintf("rpc sub notifier closed"))
    82  		}
    83  	}()
    84  
    85  	return psssub, nil
    86  }
    87  
    88  func (pssapi *API) GetAddress(topic Topic, asymmetric bool, key string) (PssAddress, error) {
    89  	var addr *PssAddress
    90  	if asymmetric {
    91  		peer, ok := pssapi.Pss.pubKeyPool[key][topic]
    92  		if !ok {
    93  			return nil, fmt.Errorf("pubkey/topic pair %x/%x doesn't exist", key, topic)
    94  		}
    95  		addr = peer.address
    96  	} else {
    97  		peer, ok := pssapi.Pss.symKeyPool[key][topic]
    98  		if !ok {
    99  			return nil, fmt.Errorf("symkey/topic pair %x/%x doesn't exist", key, topic)
   100  		}
   101  		addr = peer.address
   102  
   103  	}
   104  	return *addr, nil
   105  }
   106  
   107  // Retrieves the node's base address in hex form
   108  func (pssapi *API) BaseAddr() (PssAddress, error) {
   109  	return PssAddress(pssapi.Pss.BaseAddr()), nil
   110  }
   111  
   112  // Retrieves the node's public key in hex form
   113  func (pssapi *API) GetPublicKey() (keybytes hexutil.Bytes) {
   114  	key := pssapi.Pss.PublicKey()
   115  	keybytes = crypto.FromECDSAPub(key)
   116  	return keybytes
   117  }
   118  
   119  // Set Public key to associate with a particular Pss peer
   120  func (pssapi *API) SetPeerPublicKey(pubkey hexutil.Bytes, topic Topic, addr PssAddress) error {
   121  	pk, err := crypto.UnmarshalPubkey(pubkey)
   122  	if err != nil {
   123  		return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkey)
   124  	}
   125  	err = pssapi.Pss.SetPeerPublicKey(pk, topic, &addr)
   126  	if err != nil {
   127  		return fmt.Errorf("Invalid key: %x", pk)
   128  	}
   129  	return nil
   130  }
   131  
   132  func (pssapi *API) GetSymmetricKey(symkeyid string) (hexutil.Bytes, error) {
   133  	symkey, err := pssapi.Pss.GetSymmetricKey(symkeyid)
   134  	return hexutil.Bytes(symkey), err
   135  }
   136  
   137  func (pssapi *API) GetSymmetricAddressHint(topic Topic, symkeyid string) (PssAddress, error) {
   138  	return *pssapi.Pss.symKeyPool[symkeyid][topic].address, nil
   139  }
   140  
   141  func (pssapi *API) GetAsymmetricAddressHint(topic Topic, pubkeyid string) (PssAddress, error) {
   142  	return *pssapi.Pss.pubKeyPool[pubkeyid][topic].address, nil
   143  }
   144  
   145  func (pssapi *API) StringToTopic(topicstring string) (Topic, error) {
   146  	topicbytes := BytesToTopic([]byte(topicstring))
   147  	if topicbytes == rawTopic {
   148  		return rawTopic, errors.New("Topic string hashes to 0x00000000 and cannot be used")
   149  	}
   150  	return topicbytes, nil
   151  }
   152  
   153  func (pssapi *API) SendAsym(pubkeyhex string, topic Topic, msg hexutil.Bytes) error {
   154  	return pssapi.Pss.SendAsym(pubkeyhex, topic, msg[:])
   155  }
   156  
   157  func (pssapi *API) SendSym(symkeyhex string, topic Topic, msg hexutil.Bytes) error {
   158  	return pssapi.Pss.SendSym(symkeyhex, topic, msg[:])
   159  }
   160  
   161  func (pssapi *API) GetPeerTopics(pubkeyhex string) ([]Topic, error) {
   162  	topics, _, err := pssapi.Pss.GetPublickeyPeers(pubkeyhex)
   163  	return topics, err
   164  
   165  }
   166  
   167  func (pssapi *API) GetPeerAddress(pubkeyhex string, topic Topic) (PssAddress, error) {
   168  	return pssapi.Pss.getPeerAddress(pubkeyhex, topic)
   169  }