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  }