You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
1.2 KiB

  1. package kademlia
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. )
  8. type ID [B]byte
  9. func NewID() (ID, error) {
  10. b := make([]byte, 32)
  11. _, err := rand.Read(b)
  12. if err != nil {
  13. return ID{}, err
  14. }
  15. var id ID
  16. copy(id[:], b[:B])
  17. return id, nil
  18. }
  19. func (id ID) String() string {
  20. return hex.EncodeToString(id[:])
  21. }
  22. func (id ID) MarshalText() ([]byte, error) {
  23. return []byte(hex.EncodeToString(id[:])), nil
  24. }
  25. func (id *ID) UnmarshalText(data []byte) error {
  26. var err error
  27. var idFromStr ID
  28. idFromStr, err = IDFromString(string(data))
  29. if err != nil {
  30. return err
  31. }
  32. copy(id[:], idFromStr[:])
  33. return nil
  34. }
  35. func IDFromString(s string) (ID, error) {
  36. b, err := hex.DecodeString(s)
  37. if err != nil {
  38. return ID{}, err
  39. }
  40. var id ID
  41. copy(id[:], b[:B])
  42. return id, nil
  43. }
  44. func (idA ID) Equal(idB ID) bool {
  45. return bytes.Equal(idA[:], idB[:])
  46. }
  47. // Cmp returns true if idA > idB
  48. func (idA ID) Cmp(idB ID) bool {
  49. for i := 0; i < len(idA); i++ {
  50. if idA[i] != idB[i] {
  51. return idA[i] > idB[i]
  52. }
  53. }
  54. return false
  55. }
  56. func (idA ID) Distance(idB ID) ID {
  57. var d ID
  58. for i := 0; i < B; i++ {
  59. d[i] = idA[i] ^ idB[i]
  60. }
  61. return d
  62. }
  63. func HashData(d []byte) ID {
  64. h := sha256.Sum256(d)
  65. var r ID
  66. copy(r[:], h[:20])
  67. return r
  68. }