github.com/ethersphere/bee/v2@v2.2.0/pkg/feeds/getter.go (about)

     1  // Copyright 2021 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package feeds
     6  
     7  import (
     8  	"context"
     9  	"encoding/binary"
    10  	"errors"
    11  	"fmt"
    12  	"time"
    13  
    14  	"github.com/ethersphere/bee/v2/pkg/soc"
    15  	storage "github.com/ethersphere/bee/v2/pkg/storage"
    16  	"github.com/ethersphere/bee/v2/pkg/swarm"
    17  )
    18  
    19  // Lookup is the interface for time based feed lookup
    20  type Lookup interface {
    21  	At(ctx context.Context, at int64, after uint64) (chunk swarm.Chunk, currentIndex, nextIndex Index, err error)
    22  }
    23  
    24  // Getter encapsulates a chunk Getter getter and a feed and provides non-concurrent lookup methods
    25  type Getter struct {
    26  	getter storage.Getter
    27  	*Feed
    28  }
    29  
    30  // NewGetter constructs a feed Getter
    31  func NewGetter(getter storage.Getter, feed *Feed) *Getter {
    32  	return &Getter{getter, feed}
    33  }
    34  
    35  // Latest looks up the latest update of the feed
    36  // after is a unix time hint of the latest known update
    37  func Latest(ctx context.Context, l Lookup, after uint64) (swarm.Chunk, error) {
    38  	c, _, _, err := l.At(ctx, time.Now().Unix(), after)
    39  	return c, err
    40  }
    41  
    42  // Get creates an update of the underlying feed at the given epoch
    43  // and looks it up in the chunk Getter based on its address
    44  func (f *Getter) Get(ctx context.Context, i Index) (swarm.Chunk, error) {
    45  	addr, err := f.Feed.Update(i).Address()
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	return f.getter.Get(ctx, addr)
    50  }
    51  
    52  // FromChunk parses out the timestamp and the payload
    53  func FromChunk(ch swarm.Chunk) (uint64, []byte, error) {
    54  	s, err := soc.FromChunk(ch)
    55  	if err != nil {
    56  		return 0, nil, err
    57  	}
    58  	cac := s.WrappedChunk()
    59  	if len(cac.Data()) < 16 {
    60  		return 0, nil, errors.New("feed update payload too short")
    61  	}
    62  	payload := cac.Data()[16:]
    63  	at := binary.BigEndian.Uint64(cac.Data()[8:16])
    64  	return at, payload, nil
    65  }
    66  
    67  // UpdatedAt extracts the time of feed other than update
    68  func UpdatedAt(ch swarm.Chunk) (uint64, error) {
    69  	d := ch.Data()
    70  	if len(d) < 113 {
    71  		return 0, fmt.Errorf("too short: %d", len(d))
    72  	}
    73  	// a soc chunk with time information in the wrapped content addressed chunk
    74  	// 0-32    index,
    75  	// 65-97   signature,
    76  	// 98-105  span of wrapped chunk
    77  	// 105-113 timestamp
    78  	return binary.BigEndian.Uint64(d[105:113]), nil
    79  }