item.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package bep44
  2. import (
  3. "bytes"
  4. "crypto/ed25519"
  5. "crypto/sha1"
  6. "fmt"
  7. "time"
  8. "github.com/anacrolix/torrent/bencode"
  9. )
  10. var Empty32ByteArray [32]byte
  11. type Item struct {
  12. // time when this object was added to storage
  13. created time.Time
  14. // Value to be stored
  15. V interface{}
  16. // 32 byte ed25519 public key
  17. K [32]byte
  18. Salt []byte
  19. Sig [64]byte
  20. Cas int64
  21. Seq int64
  22. }
  23. func (i *Item) ToPut() Put {
  24. p := Put{
  25. V: i.V,
  26. Salt: i.Salt,
  27. Sig: i.Sig,
  28. Cas: i.Cas,
  29. Seq: i.Seq,
  30. }
  31. if i.K != Empty32ByteArray {
  32. p.K = &i.K
  33. }
  34. return p
  35. }
  36. // NewItem creates a new arbitrary DHT element. The distinction between storing mutable
  37. // and immutable items is the inclusion of a public key, a sequence number, signature
  38. // and an optional salt.
  39. //
  40. // cas parameter is short for compare and swap, it has similar semantics as CAS CPU
  41. // instructions. It is used to avoid race conditions when multiple nodes are writing
  42. // to the same slot in the DHT. It is optional. If present it specifies the sequence
  43. // number of the data blob being overwritten by the put.
  44. //
  45. // salt parameter is used to make possible several targets using the same private key.
  46. //
  47. // The optional seq field specifies that an item's value should only be sent if its
  48. // sequence number is greater than the given value.
  49. func NewItem(value interface{}, salt []byte, seq, cas int64, k ed25519.PrivateKey) (*Item, error) {
  50. v, err := bencode.Marshal(value)
  51. if err != nil {
  52. return nil, err
  53. }
  54. var kk [32]byte
  55. var sig [64]byte
  56. if k != nil {
  57. pk := []byte(k.Public().(ed25519.PublicKey))
  58. copy(kk[:], pk)
  59. copy(sig[:], Sign(k, salt, seq, v))
  60. }
  61. return &Item{
  62. V: value,
  63. Salt: salt,
  64. Cas: cas,
  65. Seq: seq,
  66. K: kk,
  67. Sig: sig,
  68. }, nil
  69. }
  70. func (i *Item) Target() Target {
  71. if i.IsMutable() {
  72. return sha1.Sum(append(i.K[:], i.Salt...))
  73. }
  74. return sha1.Sum(bencode.MustMarshal(i.V))
  75. }
  76. func (i *Item) Modify(value interface{}, k ed25519.PrivateKey) bool {
  77. if !i.IsMutable() {
  78. return false
  79. }
  80. v, err := bencode.Marshal(value)
  81. if err != nil {
  82. return false
  83. }
  84. i.V = value
  85. i.Seq++
  86. var sig [64]byte
  87. copy(sig[:], Sign(k, i.Salt, i.Seq, v))
  88. i.Sig = sig
  89. return true
  90. }
  91. func (s *Item) IsMutable() bool {
  92. return s.K != Empty32ByteArray
  93. }
  94. func bufferToSign(salt, bv []byte, seq int64) []byte {
  95. var bts []byte
  96. if len(salt) != 0 {
  97. bts = append(bts, []byte("4:salt")...)
  98. x := bencode.MustMarshal(salt)
  99. bts = append(bts, x...)
  100. }
  101. bts = append(bts, []byte(fmt.Sprintf("3:seqi%de1:v", seq))...)
  102. bts = append(bts, bv...)
  103. return bts
  104. }
  105. func Check(i *Item) error {
  106. bv, err := bencode.Marshal(i.V)
  107. if err != nil {
  108. return err
  109. }
  110. if len(bv) > 1000 {
  111. return ErrValueFieldTooBig
  112. }
  113. if !i.IsMutable() {
  114. return nil
  115. }
  116. if len(i.Salt) > 64 {
  117. return ErrSaltFieldTooBig
  118. }
  119. if !Verify(i.K[:], i.Salt, i.Seq, bv, i.Sig[:]) {
  120. return ErrInvalidSignature
  121. }
  122. return nil
  123. }
  124. func CheckIncoming(stored, incoming *Item) error {
  125. // If the sequence number is equal, and the value is also the same,
  126. // the node SHOULD reset its timeout counter.
  127. if stored.Seq == incoming.Seq {
  128. if bytes.Equal(
  129. bencode.MustMarshal(stored.V),
  130. bencode.MustMarshal(incoming.V),
  131. ) {
  132. return nil
  133. }
  134. }
  135. if stored.Seq >= incoming.Seq {
  136. return ErrSequenceNumberLessThanCurrent
  137. }
  138. // Cas should be ignored if not present
  139. if stored.Cas == 0 {
  140. return nil
  141. }
  142. if stored.Cas != incoming.Cas {
  143. return ErrCasHashMismatched
  144. }
  145. return nil
  146. }