github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/pss/handshake.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 // 26 27 package pss 28 29 import ( 30 "context" 31 "errors" 32 "fmt" 33 "sync" 34 "time" 35 36 "github.com/ethereum/go-ethereum/common" 37 "github.com/ethereum/go-ethereum/common/hexutil" 38 "github.com/ethereum/go-ethereum/crypto" 39 "github.com/ethereum/go-ethereum/p2p" 40 "github.com/ethereum/go-ethereum/rlp" 41 "github.com/ethereum/go-ethereum/rpc" 42 "github.com/ethereum/go-ethereum/swarm/log" 43 ) 44 45 const ( 46 IsActiveHandshake = true 47 ) 48 49 var ( 50 ctrlSingleton *HandshakeController 51 ) 52 53 const ( 54 defaultSymKeyRequestTimeout = 1000 * 8 // 55 defaultSymKeyExpiryTimeout = 1000 * 10 // 56 defaultSymKeySendLimit = 256 // 57 defaultSymKeyCapacity = 4 // 58 ) 59 60 // 61 type handshakeMsg struct { 62 From []byte 63 Limit uint16 64 Keys [][]byte 65 Request uint8 66 Topic Topic 67 } 68 69 // 70 type handshakeKey struct { 71 symKeyID *string 72 pubKeyID *string 73 limit uint16 74 count uint16 75 expiredAt time.Time 76 } 77 78 // 79 // 80 type handshake struct { 81 outKeys []handshakeKey 82 inKeys []handshakeKey 83 } 84 85 // 86 // 87 // 88 // 89 // 90 // 91 // 92 // 93 // 94 // 95 type HandshakeParams struct { 96 SymKeyRequestTimeout time.Duration 97 SymKeyExpiryTimeout time.Duration 98 SymKeySendLimit uint16 99 SymKeyCapacity uint8 100 } 101 102 // 103 func NewHandshakeParams() *HandshakeParams { 104 return &HandshakeParams{ 105 SymKeyRequestTimeout: defaultSymKeyRequestTimeout * time.Millisecond, 106 SymKeyExpiryTimeout: defaultSymKeyExpiryTimeout * time.Millisecond, 107 SymKeySendLimit: defaultSymKeySendLimit, 108 SymKeyCapacity: defaultSymKeyCapacity, 109 } 110 } 111 112 // 113 // 114 type HandshakeController struct { 115 pss *Pss 116 keyC map[string]chan []string // 117 lock sync.Mutex 118 symKeyRequestTimeout time.Duration 119 symKeyExpiryTimeout time.Duration 120 symKeySendLimit uint16 121 symKeyCapacity uint8 122 symKeyIndex map[string]*handshakeKey 123 handshakes map[string]map[Topic]*handshake 124 deregisterFuncs map[Topic]func() 125 } 126 127 // 128 // 129 // 130 func SetHandshakeController(pss *Pss, params *HandshakeParams) error { 131 ctrl := &HandshakeController{ 132 pss: pss, 133 keyC: make(map[string]chan []string), 134 symKeyRequestTimeout: params.SymKeyRequestTimeout, 135 symKeyExpiryTimeout: params.SymKeyExpiryTimeout, 136 symKeySendLimit: params.SymKeySendLimit, 137 symKeyCapacity: params.SymKeyCapacity, 138 symKeyIndex: make(map[string]*handshakeKey), 139 handshakes: make(map[string]map[Topic]*handshake), 140 deregisterFuncs: make(map[Topic]func()), 141 } 142 api := &HandshakeAPI{ 143 namespace: "pss", 144 ctrl: ctrl, 145 } 146 pss.addAPI(rpc.API{ 147 Namespace: api.namespace, 148 Version: "0.2", 149 Service: api, 150 Public: true, 151 }) 152 ctrlSingleton = ctrl 153 return nil 154 } 155 156 // 157 // 158 func (ctl *HandshakeController) validKeys(pubkeyid string, topic *Topic, in bool) (validkeys []*string) { 159 ctl.lock.Lock() 160 defer ctl.lock.Unlock() 161 now := time.Now() 162 if _, ok := ctl.handshakes[pubkeyid]; !ok { 163 return []*string{} 164 } else if _, ok := ctl.handshakes[pubkeyid][*topic]; !ok { 165 return []*string{} 166 } 167 var keystore *[]handshakeKey 168 if in { 169 keystore = &(ctl.handshakes[pubkeyid][*topic].inKeys) 170 } else { 171 keystore = &(ctl.handshakes[pubkeyid][*topic].outKeys) 172 } 173 174 for _, key := range *keystore { 175 if key.limit <= key.count { 176 ctl.releaseKey(*key.symKeyID, topic) 177 } else if !key.expiredAt.IsZero() && key.expiredAt.Before(now) { 178 ctl.releaseKey(*key.symKeyID, topic) 179 } else { 180 validkeys = append(validkeys, key.symKeyID) 181 } 182 } 183 return 184 } 185 186 // 187 // 188 func (ctl *HandshakeController) updateKeys(pubkeyid string, topic *Topic, in bool, symkeyids []string, limit uint16) { 189 ctl.lock.Lock() 190 defer ctl.lock.Unlock() 191 if _, ok := ctl.handshakes[pubkeyid]; !ok { 192 ctl.handshakes[pubkeyid] = make(map[Topic]*handshake) 193 194 } 195 if ctl.handshakes[pubkeyid][*topic] == nil { 196 ctl.handshakes[pubkeyid][*topic] = &handshake{} 197 } 198 var keystore *[]handshakeKey 199 expire := time.Now() 200 if in { 201 keystore = &(ctl.handshakes[pubkeyid][*topic].inKeys) 202 } else { 203 keystore = &(ctl.handshakes[pubkeyid][*topic].outKeys) 204 expire = expire.Add(time.Millisecond * ctl.symKeyExpiryTimeout) 205 } 206 for _, storekey := range *keystore { 207 storekey.expiredAt = expire 208 } 209 for i := 0; i < len(symkeyids); i++ { 210 storekey := handshakeKey{ 211 symKeyID: &symkeyids[i], 212 pubKeyID: &pubkeyid, 213 limit: limit, 214 } 215 *keystore = append(*keystore, storekey) 216 ctl.pss.symKeyPool[*storekey.symKeyID][*topic].protected = true 217 } 218 for i := 0; i < len(*keystore); i++ { 219 ctl.symKeyIndex[*(*keystore)[i].symKeyID] = &((*keystore)[i]) 220 } 221 } 222 223 // 224 func (ctl *HandshakeController) releaseKey(symkeyid string, topic *Topic) bool { 225 if ctl.symKeyIndex[symkeyid] == nil { 226 log.Debug("no symkey", "symkeyid", symkeyid) 227 return false 228 } 229 ctl.symKeyIndex[symkeyid].expiredAt = time.Now() 230 log.Debug("handshake release", "symkeyid", symkeyid) 231 return true 232 } 233 234 // 235 // 236 // 237 // 238 // 239 func (ctl *HandshakeController) cleanHandshake(pubkeyid string, topic *Topic, in bool, out bool) int { 240 ctl.lock.Lock() 241 defer ctl.lock.Unlock() 242 var deletecount int 243 var deletes []string 244 now := time.Now() 245 handshake := ctl.handshakes[pubkeyid][*topic] 246 log.Debug("handshake clean", "pubkey", pubkeyid, "topic", topic) 247 if in { 248 for i, key := range handshake.inKeys { 249 if key.expiredAt.Before(now) || (key.expiredAt.IsZero() && key.limit <= key.count) { 250 log.Trace("handshake in clean remove", "symkeyid", *key.symKeyID) 251 deletes = append(deletes, *key.symKeyID) 252 handshake.inKeys[deletecount] = handshake.inKeys[i] 253 deletecount++ 254 } 255 } 256 handshake.inKeys = handshake.inKeys[:len(handshake.inKeys)-deletecount] 257 } 258 if out { 259 deletecount = 0 260 for i, key := range handshake.outKeys { 261 if key.expiredAt.Before(now) && (key.expiredAt.IsZero() && key.limit <= key.count) { 262 log.Trace("handshake out clean remove", "symkeyid", *key.symKeyID) 263 deletes = append(deletes, *key.symKeyID) 264 handshake.outKeys[deletecount] = handshake.outKeys[i] 265 deletecount++ 266 } 267 } 268 handshake.outKeys = handshake.outKeys[:len(handshake.outKeys)-deletecount] 269 } 270 for _, keyid := range deletes { 271 delete(ctl.symKeyIndex, keyid) 272 ctl.pss.symKeyPool[keyid][*topic].protected = false 273 } 274 return len(deletes) 275 } 276 277 // 278 func (ctl *HandshakeController) clean() { 279 peerpubkeys := ctl.handshakes 280 for pubkeyid, peertopics := range peerpubkeys { 281 for topic := range peertopics { 282 ctl.cleanHandshake(pubkeyid, &topic, true, true) 283 } 284 } 285 } 286 287 // 288 // 289 // 290 // 291 func (ctl *HandshakeController) handler(msg []byte, p *p2p.Peer, asymmetric bool, symkeyid string) error { 292 if !asymmetric { 293 if ctl.symKeyIndex[symkeyid] != nil { 294 if ctl.symKeyIndex[symkeyid].count >= ctl.symKeyIndex[symkeyid].limit { 295 return fmt.Errorf("discarding message using expired key: %s", symkeyid) 296 } 297 ctl.symKeyIndex[symkeyid].count++ 298 log.Trace("increment symkey recv use", "symsymkeyid", symkeyid, "count", ctl.symKeyIndex[symkeyid].count, "limit", ctl.symKeyIndex[symkeyid].limit, "receiver", common.ToHex(crypto.FromECDSAPub(ctl.pss.PublicKey()))) 299 } 300 return nil 301 } 302 keymsg := &handshakeMsg{} 303 err := rlp.DecodeBytes(msg, keymsg) 304 if err == nil { 305 err := ctl.handleKeys(symkeyid, keymsg) 306 if err != nil { 307 log.Error("handlekeys fail", "error", err) 308 } 309 return err 310 } 311 return nil 312 } 313 314 // 315 // 316 // 317 // 318 // 319 // 320 // 321 // 322 // 323 // 324 func (ctl *HandshakeController) handleKeys(pubkeyid string, keymsg *handshakeMsg) error { 325 // 326 if len(keymsg.Keys) > 0 { 327 log.Debug("received handshake keys", "pubkeyid", pubkeyid, "from", keymsg.From, "count", len(keymsg.Keys)) 328 var sendsymkeyids []string 329 for _, key := range keymsg.Keys { 330 sendsymkey := make([]byte, len(key)) 331 copy(sendsymkey, key) 332 var address PssAddress 333 copy(address[:], keymsg.From) 334 sendsymkeyid, err := ctl.pss.setSymmetricKey(sendsymkey, keymsg.Topic, &address, false, false) 335 if err != nil { 336 return err 337 } 338 sendsymkeyids = append(sendsymkeyids, sendsymkeyid) 339 } 340 if len(sendsymkeyids) > 0 { 341 ctl.updateKeys(pubkeyid, &keymsg.Topic, false, sendsymkeyids, keymsg.Limit) 342 343 ctl.alertHandshake(pubkeyid, sendsymkeyids) 344 } 345 } 346 347 // 348 if keymsg.Request > 0 { 349 _, err := ctl.sendKey(pubkeyid, &keymsg.Topic, keymsg.Request) 350 if err != nil { 351 return err 352 } 353 } 354 355 return nil 356 } 357 358 // 359 // 360 // 361 // 362 // 363 // 364 func (ctl *HandshakeController) sendKey(pubkeyid string, topic *Topic, keycount uint8) ([]string, error) { 365 366 var requestcount uint8 367 to := &PssAddress{} 368 if _, ok := ctl.pss.pubKeyPool[pubkeyid]; !ok { 369 return []string{}, errors.New("Invalid public key") 370 } else if psp, ok := ctl.pss.pubKeyPool[pubkeyid][*topic]; ok { 371 to = psp.address 372 } 373 374 recvkeys := make([][]byte, keycount) 375 recvkeyids := make([]string, keycount) 376 ctl.lock.Lock() 377 if _, ok := ctl.handshakes[pubkeyid]; !ok { 378 ctl.handshakes[pubkeyid] = make(map[Topic]*handshake) 379 } 380 ctl.lock.Unlock() 381 382 // 383 outkeys := ctl.validKeys(pubkeyid, topic, false) 384 if len(outkeys) < int(ctl.symKeyCapacity) { 385 // 386 requestcount = ctl.symKeyCapacity 387 } 388 // 389 if requestcount == 0 && keycount == 0 { 390 return []string{}, nil 391 } 392 393 // 394 for i := 0; i < len(recvkeyids); i++ { 395 var err error 396 recvkeyids[i], err = ctl.pss.GenerateSymmetricKey(*topic, to, true) 397 if err != nil { 398 return []string{}, fmt.Errorf("set receive symkey fail (pubkey %x topic %x): %v", pubkeyid, topic, err) 399 } 400 recvkeys[i], err = ctl.pss.GetSymmetricKey(recvkeyids[i]) 401 if err != nil { 402 return []string{}, fmt.Errorf("GET Generated outgoing symkey fail (pubkey %x topic %x): %v", pubkeyid, topic, err) 403 } 404 } 405 ctl.updateKeys(pubkeyid, topic, true, recvkeyids, ctl.symKeySendLimit) 406 407 // 408 recvkeymsg := &handshakeMsg{ 409 From: ctl.pss.BaseAddr(), 410 Keys: recvkeys, 411 Request: requestcount, 412 Limit: ctl.symKeySendLimit, 413 Topic: *topic, 414 } 415 log.Debug("sending our symkeys", "pubkey", pubkeyid, "symkeys", recvkeyids, "limit", ctl.symKeySendLimit, "requestcount", requestcount, "keycount", len(recvkeys)) 416 recvkeybytes, err := rlp.EncodeToBytes(recvkeymsg) 417 if err != nil { 418 return []string{}, fmt.Errorf("rlp keymsg encode fail: %v", err) 419 } 420 // 421 err = ctl.pss.SendAsym(pubkeyid, *topic, recvkeybytes) 422 if err != nil { 423 return []string{}, fmt.Errorf("Send symkey failed: %v", err) 424 } 425 return recvkeyids, nil 426 } 427 428 // 429 func (ctl *HandshakeController) alertHandshake(pubkeyid string, symkeys []string) chan []string { 430 if len(symkeys) > 0 { 431 if _, ok := ctl.keyC[pubkeyid]; ok { 432 ctl.keyC[pubkeyid] <- symkeys 433 close(ctl.keyC[pubkeyid]) 434 delete(ctl.keyC, pubkeyid) 435 } 436 return nil 437 } 438 if _, ok := ctl.keyC[pubkeyid]; !ok { 439 ctl.keyC[pubkeyid] = make(chan []string) 440 } 441 return ctl.keyC[pubkeyid] 442 } 443 444 type HandshakeAPI struct { 445 namespace string 446 ctrl *HandshakeController 447 } 448 449 // 450 // 451 // 452 // 453 // 454 // 455 // 456 // 457 // 458 // 459 // 460 // 461 // 462 // 463 func (api *HandshakeAPI) Handshake(pubkeyid string, topic Topic, sync bool, flush bool) (keys []string, err error) { 464 var hsc chan []string 465 var keycount uint8 466 if flush { 467 keycount = api.ctrl.symKeyCapacity 468 } else { 469 validkeys := api.ctrl.validKeys(pubkeyid, &topic, false) 470 keycount = api.ctrl.symKeyCapacity - uint8(len(validkeys)) 471 } 472 if keycount == 0 { 473 return keys, errors.New("Incoming symmetric key store is already full") 474 } 475 if sync { 476 hsc = api.ctrl.alertHandshake(pubkeyid, []string{}) 477 } 478 _, err = api.ctrl.sendKey(pubkeyid, &topic, keycount) 479 if err != nil { 480 return keys, err 481 } 482 if sync { 483 ctx, cancel := context.WithTimeout(context.Background(), api.ctrl.symKeyRequestTimeout) 484 defer cancel() 485 select { 486 case keys = <-hsc: 487 log.Trace("sync handshake response receive", "key", keys) 488 case <-ctx.Done(): 489 return []string{}, errors.New("timeout") 490 } 491 } 492 return keys, nil 493 } 494 495 // 496 func (api *HandshakeAPI) AddHandshake(topic Topic) error { 497 api.ctrl.deregisterFuncs[topic] = api.ctrl.pss.Register(&topic, api.ctrl.handler) 498 return nil 499 } 500 501 // 502 func (api *HandshakeAPI) RemoveHandshake(topic *Topic) error { 503 if _, ok := api.ctrl.deregisterFuncs[*topic]; ok { 504 api.ctrl.deregisterFuncs[*topic]() 505 } 506 return nil 507 } 508 509 // 510 // 511 // 512 // 513 // 514 // 515 func (api *HandshakeAPI) GetHandshakeKeys(pubkeyid string, topic Topic, in bool, out bool) (keys []string, err error) { 516 if in { 517 for _, inkey := range api.ctrl.validKeys(pubkeyid, &topic, true) { 518 keys = append(keys, *inkey) 519 } 520 } 521 if out { 522 for _, outkey := range api.ctrl.validKeys(pubkeyid, &topic, false) { 523 keys = append(keys, *outkey) 524 } 525 } 526 return keys, nil 527 } 528 529 // 530 // 531 func (api *HandshakeAPI) GetHandshakeKeyCapacity(symkeyid string) (uint16, error) { 532 storekey := api.ctrl.symKeyIndex[symkeyid] 533 if storekey == nil { 534 return 0, fmt.Errorf("invalid symkey id %s", symkeyid) 535 } 536 return storekey.limit - storekey.count, nil 537 } 538 539 // 540 // 541 func (api *HandshakeAPI) GetHandshakePublicKey(symkeyid string) (string, error) { 542 storekey := api.ctrl.symKeyIndex[symkeyid] 543 if storekey == nil { 544 return "", fmt.Errorf("invalid symkey id %s", symkeyid) 545 } 546 return *storekey.pubKeyID, nil 547 } 548 549 // 550 // 551 // 552 // 553 // 554 func (api *HandshakeAPI) ReleaseHandshakeKey(pubkeyid string, topic Topic, symkeyid string, flush bool) (removed bool, err error) { 555 removed = api.ctrl.releaseKey(symkeyid, &topic) 556 if removed && flush { 557 api.ctrl.cleanHandshake(pubkeyid, &topic, true, true) 558 } 559 return 560 } 561 562 // 563 // 564 // 565 // 566 func (api *HandshakeAPI) SendSym(symkeyid string, topic Topic, msg hexutil.Bytes) (err error) { 567 err = api.ctrl.pss.SendSym(symkeyid, topic, msg[:]) 568 if api.ctrl.symKeyIndex[symkeyid] != nil { 569 if api.ctrl.symKeyIndex[symkeyid].count >= api.ctrl.symKeyIndex[symkeyid].limit { 570 return errors.New("attempted send with expired key") 571 } 572 api.ctrl.symKeyIndex[symkeyid].count++ 573 log.Trace("increment symkey send use", "symkeyid", symkeyid, "count", api.ctrl.symKeyIndex[symkeyid].count, "limit", api.ctrl.symKeyIndex[symkeyid].limit, "receiver", common.ToHex(crypto.FromECDSAPub(api.ctrl.pss.PublicKey()))) 574 } 575 return 576 }