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