github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/addrbook.go (about) 1 package dht 2 3 import ( 4 "crypto/rand" 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 "os" 9 "sync" 10 11 "github.com/turingchain2020/turingchain/common/db" 12 p2pty "github.com/turingchain2020/turingchain/system/p2p/dht/types" 13 "github.com/turingchain2020/turingchain/types" 14 "github.com/turingchain2020/turingchain/wallet/bipwallet" 15 "github.com/libp2p/go-libp2p-core/crypto" 16 "github.com/libp2p/go-libp2p-core/peer" 17 ) 18 19 const ( 20 addrkeyTag = "mutiaddrs" 21 privKeyTag = "privkey" 22 privKeyCompressBytesLen = 32 23 ) 24 25 // AddrBook peer address manager 26 type AddrBook struct { 27 mtx sync.Mutex 28 cfg *types.P2P 29 privkey string 30 pubkey string 31 bookDb db.DB 32 } 33 34 // NewAddrBook new addr book 35 func NewAddrBook(cfg *types.P2P) *AddrBook { 36 a := &AddrBook{ 37 cfg: cfg, 38 } 39 dbPath := cfg.DbPath + "/" + p2pty.DHTTypeName 40 a.bookDb = db.NewDB("addrBook", a.cfg.Driver, dbPath, a.cfg.DbCache) 41 a.loadDb() 42 return a 43 44 } 45 46 // AddrsInfo get addr infos 47 func (a *AddrBook) AddrsInfo() []peer.AddrInfo { 48 var addrsInfo []peer.AddrInfo 49 if a.bookDb == nil { 50 return addrsInfo 51 } 52 53 addrsInfoBs, err := a.bookDb.Get([]byte(addrkeyTag)) 54 if err != nil { 55 log.Error("LoadAddrsInfo", " Get addrkeyTag", err.Error()) 56 return addrsInfo 57 } 58 59 err = json.Unmarshal(addrsInfoBs, &addrsInfo) 60 if err != nil { 61 log.Error("LoadAddrsInfo", "Unmarshal err", err.Error()) 62 return nil 63 } 64 65 return addrsInfo 66 } 67 68 func (a *AddrBook) loadDb() bool { 69 70 privkey, err := a.bookDb.Get([]byte(privKeyTag)) 71 if len(privkey) != 0 && err == nil { 72 pubkey, err := GenPubkey(string(privkey)) 73 if err != nil { 74 log.Error("genPubkey", "err", err.Error()) 75 panic(err) 76 } 77 a.setKey(string(privkey), pubkey) 78 return true 79 } 80 81 return false 82 83 } 84 85 //Randkey Rand keypair 86 func (a *AddrBook) Randkey() crypto.PrivKey { 87 a.initKey() 88 return a.GetPrivkey() 89 } 90 func (a *AddrBook) initKey() { 91 92 priv, pub, err := GenPrivPubkey() 93 if err != nil { 94 var maxRetry = 10 95 for i := 0; i < maxRetry; i++ { 96 priv, pub, err = GenPrivPubkey() 97 if err == nil { 98 break 99 } 100 if i == maxRetry-1 && err != nil { 101 panic(err.Error()) 102 } 103 } 104 105 } 106 107 a.saveKey(hex.EncodeToString(priv), hex.EncodeToString(pub)) 108 } 109 110 func (a *AddrBook) saveKey(priv, pub string) { 111 a.setKey(priv, pub) 112 err := a.bookDb.Set([]byte(privKeyTag), []byte(priv)) 113 if err != nil { 114 panic(err) 115 } 116 } 117 118 // GetPrivkey get private key 119 func (a *AddrBook) GetPrivkey() crypto.PrivKey { 120 a.mtx.Lock() 121 defer a.mtx.Unlock() 122 if a.privkey == "" { 123 return nil 124 } 125 keybytes, err := hex.DecodeString(a.privkey) 126 if err != nil { 127 log.Error("GetPrivkey", "DecodeString Error", err.Error()) 128 return nil 129 } 130 log.Debug("GetPrivkey", "privsize", len(keybytes)) 131 132 privkey, err := crypto.UnmarshalSecp256k1PrivateKey(keybytes) 133 if err != nil { 134 privkey, err = crypto.UnmarshalPrivateKey(keybytes) 135 if err != nil { 136 log.Error("GetPrivkey", "UnmarshalPrivateKey", err.Error()) 137 return nil 138 } 139 140 } 141 142 return privkey 143 } 144 145 // GetPrivPubKey return privkey and pubkey 146 func (a *AddrBook) GetPrivPubKey() (string, string) { 147 a.mtx.Lock() 148 defer a.mtx.Unlock() 149 return a.privkey, a.pubkey 150 } 151 152 func (a *AddrBook) setKey(privkey, pubkey string) { 153 a.mtx.Lock() 154 defer a.mtx.Unlock() 155 a.privkey = privkey 156 a.pubkey = pubkey 157 158 } 159 160 // SaveAddr save addr 161 func (a *AddrBook) SaveAddr(addrinfos []peer.AddrInfo) error { 162 163 jsonBytes, err := json.Marshal(addrinfos) 164 if err != nil { 165 log.Error("Failed to save AddrBook to file", "err", err) 166 return err 167 } 168 log.Debug("saveToDb", "addrs", string(jsonBytes)) 169 return a.bookDb.Set([]byte(addrkeyTag), jsonBytes) 170 171 } 172 173 // StoreHostID store host id into file 174 func (a *AddrBook) StoreHostID(id peer.ID, path string) { 175 dbPath := path + "/" + p2pty.DHTTypeName 176 if os.MkdirAll(dbPath, 0755) != nil { 177 return 178 } 179 180 pf, err := os.Create(fmt.Sprintf("%v/%v", dbPath, id.Pretty())) 181 if err != nil { 182 log.Error("StoreHostId", "Create file", err.Error()) 183 return 184 } 185 186 defer pf.Close() 187 var peerInfo = make(map[string]interface{}) 188 var info = make(map[string]interface{}) 189 pubkey, err := PeerIDToPubkey(id.Pretty()) 190 if err == nil { 191 info["pubkey"] = pubkey 192 pbytes, _ := hex.DecodeString(pubkey) 193 addr, _ := bipwallet.PubToAddress(pbytes) 194 info["address"] = addr 195 } 196 197 peerInfo[id.Pretty()] = info 198 bs, err := json.MarshalIndent(peerInfo, "", "\t") 199 if err != nil { 200 log.Error("StoreHostId", "MarshalIndent", err.Error()) 201 return 202 } 203 _, err = pf.Write(bs) 204 if err != nil { 205 return 206 } 207 208 } 209 210 // GenPrivPubkey return key and pubkey in bytes 211 func GenPrivPubkey() ([]byte, []byte, error) { 212 priv, pub, err := crypto.GenerateSecp256k1Key(rand.Reader) 213 //priv, pub, err := crypto.GenerateKeyPairWithReader(crypto.Secp256k1, 2048, rand.Reader) 214 if err != nil { 215 return nil, nil, err 216 } 217 218 privkey, err := priv.Raw() 219 if err != nil { 220 return nil, nil, err 221 222 } 223 pubkey, err := pub.Raw() 224 if err != nil { 225 return nil, nil, err 226 227 } 228 return privkey, pubkey, nil 229 230 } 231 232 // GenPubkey generate public key 233 func GenPubkey(key string) (string, error) { 234 keybytes, err := hex.DecodeString(key) 235 if err != nil { 236 log.Error("DecodeString Error", "Error", err.Error()) 237 return "", err 238 } 239 240 log.Info("GenPubkey", "key size", len(keybytes)) 241 privkey, err := crypto.UnmarshalSecp256k1PrivateKey(keybytes) 242 if err != nil { 243 244 privkey, err = crypto.UnmarshalPrivateKey(keybytes) 245 if err != nil { 246 //切换 247 log.Error("genPubkey", "UnmarshalPrivateKey", err.Error()) 248 return "", err 249 } 250 } 251 252 pubkey, err := privkey.GetPublic().Raw() 253 if err != nil { 254 log.Error("genPubkey", "GetPubkey", err.Error()) 255 return "", err 256 } 257 return hex.EncodeToString(pubkey), nil 258 259 } 260 261 //PeerIDToPubkey 提供节点ID转换为pubkey,进而通过pubkey创建turingchain 地址的功能 262 func PeerIDToPubkey(id string) (string, error) { 263 //encodeIdStr := "16Uiu2HAm7vDB7XDuEv8XNPcoPqumVngsjWoogGXENNDXVYMiCJHM" 264 //hexpubStr:="02b99bc73bfb522110634d5644d476b21b3171eefab517da0646ef2aba39dbf4a0" 265 //turingchain address:13ohj5JH6NE15ENfuQRneqGdg29nT27K3k 266 pID, err := peer.Decode(id) 267 if err != nil { 268 return "", err 269 } 270 271 pub, err := pID.ExtractPublicKey() 272 if err != nil { 273 return "", err 274 } 275 276 pbs, err := pub.Raw() 277 if err != nil { 278 return "", err 279 } 280 return hex.EncodeToString(pbs), nil 281 282 }