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 }