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 }