github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/gossip/protocols/dag/dagstream/dagstreamseeder/seeder.go (about) 1 package dagstreamseeder 2 3 import ( 4 "errors" 5 6 "github.com/unicornultrafoundation/go-u2u/rlp" 7 8 "github.com/unicornultrafoundation/go-helios/gossip/basestream" 9 "github.com/unicornultrafoundation/go-helios/gossip/basestream/basestreamseeder" 10 "github.com/unicornultrafoundation/go-helios/hash" 11 12 "github.com/unicornultrafoundation/go-u2u/gossip/protocols/dag/dagstream" 13 ) 14 15 var ( 16 ErrWrongType = errors.New("wrong request type") 17 ErrWrongSelectorLen = errors.New("wrong event selector length") 18 ) 19 20 type Seeder struct { 21 *basestreamseeder.BaseSeeder 22 } 23 24 type Callbacks struct { 25 ForEachEvent func(start []byte, onEvent func(key hash.Event, eventB rlp.RawValue) bool) 26 } 27 28 type Peer struct { 29 ID string 30 SendChunk func(dagstream.Response, hash.Events) error 31 Misbehaviour func(error) 32 } 33 34 func New(cfg Config, callbacks Callbacks) *Seeder { 35 return &Seeder{ 36 BaseSeeder: basestreamseeder.New(basestreamseeder.Config(cfg), basestreamseeder.Callbacks{ 37 ForEachItem: func(start basestream.Locator, rType basestream.RequestType, onKey func(basestream.Locator) bool, onAppended func(basestream.Payload) bool) basestream.Payload { 38 res := &dagstream.Payload{ 39 IDs: hash.Events{}, 40 Events: []rlp.RawValue{}, 41 Size: 0, 42 } 43 callbacks.ForEachEvent(start.(dagstream.Locator), func(key hash.Event, eventB rlp.RawValue) bool { 44 if !onKey(dagstream.Locator(key.Bytes())) { 45 return false 46 } 47 if rType == dagstream.RequestIDs { 48 res.AddID(key, len(eventB)) 49 } else { 50 res.AddEvent(key, eventB) 51 } 52 return onAppended(res) 53 }) 54 return res 55 }, 56 }), 57 } 58 } 59 60 func (s *Seeder) NotifyRequestReceived(peer Peer, r dagstream.Request) (err error, peerErr error) { 61 if len(r.Session.Start) > len(hash.ZeroEvent) || len(r.Session.Stop) > len(hash.ZeroEvent) { 62 return nil, ErrWrongSelectorLen 63 } 64 if r.Type != dagstream.RequestIDs && r.Type != dagstream.RequestEvents { 65 return nil, ErrWrongType 66 } 67 rType := r.Type 68 return s.BaseSeeder.NotifyRequestReceived(basestreamseeder.Peer{ 69 ID: peer.ID, 70 SendChunk: func(response basestream.Response) error { 71 payload := response.Payload.(*dagstream.Payload) 72 payloadIDs := payload.IDs 73 if rType == dagstream.RequestEvents { 74 payloadIDs = payloadIDs[:0] 75 } 76 return peer.SendChunk(dagstream.Response{ 77 SessionID: response.SessionID, 78 Done: response.Done, 79 IDs: payloadIDs, 80 Events: payload.Events, 81 }, payload.IDs) 82 }, 83 Misbehaviour: peer.Misbehaviour, 84 }, basestream.Request{ 85 Session: basestream.Session{ 86 ID: r.Session.ID, 87 Start: r.Session.Start, 88 Stop: r.Session.Stop, 89 }, 90 Type: r.Type, 91 MaxPayloadNum: uint32(r.Limit.Num), 92 MaxPayloadSize: r.Limit.Size, 93 MaxChunks: r.MaxChunks, 94 }) 95 }