github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/pss/api.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:44</date>
    10  //</624450116329148416>
    11  
    12  
    13  package pss
    14  
    15  import (
    16  	"context"
    17  	"errors"
    18  	"fmt"
    19  
    20  	"github.com/ethereum/go-ethereum/common/hexutil"
    21  	"github.com/ethereum/go-ethereum/crypto"
    22  	"github.com/ethereum/go-ethereum/p2p"
    23  	"github.com/ethereum/go-ethereum/rpc"
    24  	"github.com/ethereum/go-ethereum/swarm/log"
    25  )
    26  
    27  //使用PSS API时用于接收PSS消息的包装器
    28  //提供对消息发送者的访问
    29  type APIMsg struct {
    30  	Msg        hexutil.Bytes
    31  	Asymmetric bool
    32  	Key        string
    33  }
    34  
    35  //通过PSS的API可访问的其他公共方法
    36  type API struct {
    37  	*Pss
    38  }
    39  
    40  func NewAPI(ps *Pss) *API {
    41  	return &API{Pss: ps}
    42  }
    43  
    44  //为调用者创建新的订阅。启用对传入消息的外部处理。
    45  //
    46  //在PSS中为提供的主题注册了一个新的处理程序
    47  //
    48  //与此主题匹配的节点的所有传入消息都将封装在apimsg中
    49  //结构并发送到订阅服务器
    50  func (pssapi *API) Receive(ctx context.Context, topic Topic, raw bool, prox bool) (*rpc.Subscription, error) {
    51  	notifier, supported := rpc.NotifierFromContext(ctx)
    52  	if !supported {
    53  		return nil, fmt.Errorf("Subscribe not supported")
    54  	}
    55  
    56  	psssub := notifier.CreateSubscription()
    57  
    58  	hndlr := NewHandler(func(msg []byte, p *p2p.Peer, asymmetric bool, keyid string) error {
    59  		apimsg := &APIMsg{
    60  			Msg:        hexutil.Bytes(msg),
    61  			Asymmetric: asymmetric,
    62  			Key:        keyid,
    63  		}
    64  		if err := notifier.Notify(psssub.ID, apimsg); err != nil {
    65  			log.Warn(fmt.Sprintf("notification on pss sub topic rpc (sub %v) msg %v failed!", psssub.ID, msg))
    66  		}
    67  		return nil
    68  	})
    69  	if raw {
    70  		hndlr.caps.raw = true
    71  	}
    72  	if prox {
    73  		hndlr.caps.prox = true
    74  	}
    75  
    76  	deregf := pssapi.Register(&topic, hndlr)
    77  	go func() {
    78  		defer deregf()
    79  		select {
    80  		case err := <-psssub.Err():
    81  			log.Warn(fmt.Sprintf("caught subscription error in pss sub topic %x: %v", topic, err))
    82  		case <-notifier.Closed():
    83  			log.Warn(fmt.Sprintf("rpc sub notifier closed"))
    84  		}
    85  	}()
    86  
    87  	return psssub, nil
    88  }
    89  
    90  func (pssapi *API) GetAddress(topic Topic, asymmetric bool, key string) (PssAddress, error) {
    91  	var addr PssAddress
    92  	if asymmetric {
    93  		peer, ok := pssapi.Pss.pubKeyPool[key][topic]
    94  		if !ok {
    95  			return nil, fmt.Errorf("pubkey/topic pair %x/%x doesn't exist", key, topic)
    96  		}
    97  		addr = peer.address
    98  	} else {
    99  		peer, ok := pssapi.Pss.symKeyPool[key][topic]
   100  		if !ok {
   101  			return nil, fmt.Errorf("symkey/topic pair %x/%x doesn't exist", key, topic)
   102  		}
   103  		addr = peer.address
   104  
   105  	}
   106  	return addr, nil
   107  }
   108  
   109  //以十六进制形式检索节点的基地址
   110  func (pssapi *API) BaseAddr() (PssAddress, error) {
   111  	return PssAddress(pssapi.Pss.BaseAddr()), nil
   112  }
   113  
   114  //以十六进制形式检索节点的公钥
   115  func (pssapi *API) GetPublicKey() (keybytes hexutil.Bytes) {
   116  	key := pssapi.Pss.PublicKey()
   117  	keybytes = crypto.FromECDSAPub(key)
   118  	return keybytes
   119  }
   120  
   121  //将公钥设置为与特定PSS对等机关联
   122  func (pssapi *API) SetPeerPublicKey(pubkey hexutil.Bytes, topic Topic, addr PssAddress) error {
   123  	pk, err := crypto.UnmarshalPubkey(pubkey)
   124  	if err != nil {
   125  		return fmt.Errorf("Cannot unmarshal pubkey: %x", pubkey)
   126  	}
   127  	err = pssapi.Pss.SetPeerPublicKey(pk, topic, addr)
   128  	if err != nil {
   129  		return fmt.Errorf("Invalid key: %x", pk)
   130  	}
   131  	return nil
   132  }
   133  
   134  func (pssapi *API) GetSymmetricKey(symkeyid string) (hexutil.Bytes, error) {
   135  	symkey, err := pssapi.Pss.GetSymmetricKey(symkeyid)
   136  	return hexutil.Bytes(symkey), err
   137  }
   138  
   139  func (pssapi *API) GetSymmetricAddressHint(topic Topic, symkeyid string) (PssAddress, error) {
   140  	return pssapi.Pss.symKeyPool[symkeyid][topic].address, nil
   141  }
   142  
   143  func (pssapi *API) GetAsymmetricAddressHint(topic Topic, pubkeyid string) (PssAddress, error) {
   144  	return pssapi.Pss.pubKeyPool[pubkeyid][topic].address, nil
   145  }
   146  
   147  func (pssapi *API) StringToTopic(topicstring string) (Topic, error) {
   148  	topicbytes := BytesToTopic([]byte(topicstring))
   149  	if topicbytes == rawTopic {
   150  		return rawTopic, errors.New("Topic string hashes to 0x00000000 and cannot be used")
   151  	}
   152  	return topicbytes, nil
   153  }
   154  
   155  func (pssapi *API) SendAsym(pubkeyhex string, topic Topic, msg hexutil.Bytes) error {
   156  	if err := validateMsg(msg); err != nil {
   157  		return err
   158  	}
   159  	return pssapi.Pss.SendAsym(pubkeyhex, topic, msg[:])
   160  }
   161  
   162  func (pssapi *API) SendSym(symkeyhex string, topic Topic, msg hexutil.Bytes) error {
   163  	if err := validateMsg(msg); err != nil {
   164  		return err
   165  	}
   166  	return pssapi.Pss.SendSym(symkeyhex, topic, msg[:])
   167  }
   168  
   169  func (pssapi *API) SendRaw(addr hexutil.Bytes, topic Topic, msg hexutil.Bytes) error {
   170  	if err := validateMsg(msg); err != nil {
   171  		return err
   172  	}
   173  	return pssapi.Pss.SendRaw(PssAddress(addr), topic, msg[:])
   174  }
   175  
   176  func (pssapi *API) GetPeerTopics(pubkeyhex string) ([]Topic, error) {
   177  	topics, _, err := pssapi.Pss.GetPublickeyPeers(pubkeyhex)
   178  	return topics, err
   179  
   180  }
   181  
   182  func (pssapi *API) GetPeerAddress(pubkeyhex string, topic Topic) (PssAddress, error) {
   183  	return pssapi.Pss.getPeerAddress(pubkeyhex, topic)
   184  }
   185  
   186  func validateMsg(msg []byte) error {
   187  	if len(msg) == 0 {
   188  		return errors.New("invalid message length")
   189  	}
   190  	return nil
   191  }
   192