tracker

package
v0.0.0-...-8bae245 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 28, 2025 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BlockProvider

type BlockProvider interface {
	GetBlockByHash(hash ethgo.Hash, full bool) (*ethgo.Block, error)
	GetBlockByNumber(i ethgo.BlockNumber, full bool) (*ethgo.Block, error)
	GetLogs(filter *ethgo.LogFilter) ([]*ethgo.Log, error)
	ChainID() (*big.Int, error)
}

BlockProvider is an interface that defines methods for retrieving blocks and logs from a blockchain

type EventSubscriber

type EventSubscriber interface {
	AddLog(chainID *big.Int, log *ethgo.Log) error
}

EventSubscriber is an interface that defines methods for handling tracked logs (events) from a blockchain

type EventTracker

type EventTracker struct {
	// contains filtered or unexported fields
}

EventTracker represents a tracker for events on desired contracts on some chain

func NewEventTracker

func NewEventTracker(config *EventTrackerConfig, store eventStore.EventTrackerStore) (*EventTracker, error)

NewEventTracker is a constructor function that creates a new instance of the EventTracker struct.

Example Usage:

config := &EventTracker{
	RpcEndpoint:           "http://some-json-rpc-url.com",
	StartBlockFromConfig:  100_000,
	NumBlockConfirmations: 10,
	SyncBatchSize:         20,
	NumOfBlocksToReconcile:10_000,
	PollInterval:          2 * time.Second,
	Logger:                logger,
	Store:                 store,
	EventSubscriber:       subscriber,
	Provider:              provider,
	LogFilter: TrackerLogFilter{
		Addresses: []ethgo.Address{addressOfSomeContract},
		IDs:       []ethgo.Hash{idHashOfSomeEvent},
	},
}
	t := NewEventTracker(config)

Inputs:

  • config (TrackerConfig): configuration of EventTracker.
  • store: implementation of EventTrackerStore interface

Outputs:

  • A new instance of the EventTracker struct.

func (*EventTracker) Start

func (e *EventTracker) Start(ctx context.Context)

Start is a method in the EventTracker struct that starts the tracking of blocks and retrieval of logs from given blocks from the tracked chain. If the tracker was turned off (node was down) for some time, it will sync up all the missed blocks and logs from the last start (in regards to NumOfBlocksToReconcile field in config). It should be called once the EventTracker is created and configured and probably from separate goroutine.

Inputs: - ctx: A context.Context instance to manage cancellation and timeouts.

type EventTrackerConfig

type EventTrackerConfig struct {
	// RPCEndpoint is the full json rpc url on some node on a tracked chain
	RPCEndpoint string `json:"rpcEndpoint"`

	// NumBlockConfirmations defines how many blocks must pass from a certain block,
	// to consider that block as final on the tracked chain.
	// This is very important for reorgs, and events from the given block will only be
	// processed if it hits this confirmation mark.
	// (e.g., NumBlockConfirmations = 3, and if the last tracked block is 10,
	// events from block 10, will only be processed when we get block 13 from the tracked chain)
	NumBlockConfirmations uint64 `json:"numBlockConfirmations"`

	// SyncBatchSize defines a batch size of blocks that will be gotten from tracked chain,
	// when tracker is out of sync and needs to sync a number of blocks.
	// (e.g., SyncBatchSize = 10, trackers last processed block is 10, latest block on tracked chain is 100,
	// it will get blocks 11-20, get logs from confirmed blocks of given batch, remove processed confirm logs
	// from memory, and continue to the next batch)
	SyncBatchSize uint64 `json:"syncBatchSize"`

	// NumOfBlocksToReconcile defines how many blocks we will sync up from the latest block on tracked chain.
	// If a node that has tracker, was offline for days, months, a year, it will miss a lot of blocks.
	// In the meantime, we expect the rest of nodes to have collected the desired events and did their
	// logic with them, continuing consensus and relayer stuff.
	// In order to not waste too much unnecessary time in syncing all those blocks, with NumOfBlocksToReconcile,
	// we tell the tracker to sync only latestBlock.Number - NumOfBlocksToReconcile number of blocks.
	NumOfBlocksToReconcile uint64 `json:"numOfBlocksToReconcile"`

	// PollInterval defines a time interval in which tracker polls json rpc node
	// for latest block on the tracked chain.
	PollInterval time.Duration `json:"pollInterval"`

	// LogFilter defines which events are tracked and from which contracts on the tracked chain
	LogFilter map[ethgo.Address][]ethgo.Hash `json:"logFilter"`

	// StartBlockFromConfig defines the block from which the tracker will start tracking events.
	StartBlockFromGenesis uint64 `json:"startBlockFromGenesis"`

	// Logger is the logger instance for event tracker
	Logger hcf.Logger `json:"-"`

	// BlockProvider is the implementation of a provider that returns blocks and logs from tracked chain
	BlockProvider BlockProvider `json:"-"`

	// Client is the jsonrpc client
	RPCClient *jsonrpc.Client `json:"-"`

	// EventSubscriber is the subscriber that requires events tracked by the event tracker
	EventSubscriber EventSubscriber `json:"-"`
}

EventTrackerConfig is a struct that holds configuration of a EventTracker

type TrackerBlockContainer

type TrackerBlockContainer struct {
	// contains filtered or unexported fields
}

TrackerBlockContainer is a struct used to cache and manage tracked blocks from tracked chain. It keeps a map of block numbers to hashes, a slice of block numbers to process, and the last processed confirmed block number. It also uses a mutex to handle concurrent access to the struct

func NewTrackerBlockContainer

func NewTrackerBlockContainer(lastProcessed uint64) *TrackerBlockContainer

NewTrackerBlockContainer is a constructor function that creates a new instance of the TrackerBlockContainer struct.

Example Usage:

t := NewTrackerBlockContainer(1)

Inputs:

  • lastProcessed (uint64): The last processed block number.

Outputs:

  • A new instance of the TrackerBlockContainer struct with the lastProcessedConfirmedBlock field set to the input lastProcessed block number and an empty numToHashMap map.

func (*TrackerBlockContainer) AcquireWriteLock

func (t *TrackerBlockContainer) AcquireWriteLock()

AcquireWriteLock acquires the write lock on the TrackerBlockContainer

func (*TrackerBlockContainer) AddBlock

func (t *TrackerBlockContainer) AddBlock(block *ethgo.Block) error

AddBlock adds a new block to the tracker by storing its number and hash in the numToHashMap map and appending the block number to the blocks slice.

Inputs:

  • block (ethgo.Block): The block to be added to the tracker cache for later processing, once it hits confirmation number.

func (*TrackerBlockContainer) BlockExists

func (t *TrackerBlockContainer) BlockExists(block *ethgo.Block) bool

BlockExists checks if a block is already present in the container memory.

Inputs: - block (*ethgo.Block): The Ethereum block to check.

Returns: - true if the block exists in the memory container and matches the stored hash.

func (*TrackerBlockContainer) CleanState

func (t *TrackerBlockContainer) CleanState()

CleanState resets the state of the TrackerBlockContainer by clearing the numToHashMap map and setting the blocks slice to an empty slice Called when a reorg happened or we are completely out of sync

func (*TrackerBlockContainer) GetConfirmedBlocks

func (t *TrackerBlockContainer) GetConfirmedBlocks(numBlockConfirmations uint64) []uint64

GetConfirmedBlocks returns a slice of uint64 representing the block numbers of confirmed blocks.

Example Usage:

t := NewTrackerBlockContainer(2)
t.AddBlock(&ethgo.Block{Number: 1, Hash: "hash1"})
t.AddBlock(&ethgo.Block{Number: 2, Hash: "hash2"})
t.AddBlock(&ethgo.Block{Number: 3, Hash: "hash3"})

confirmedBlocks := t.GetConfirmedBlocks(2)
fmt.Println(confirmedBlocks) // Output: [1]

Inputs:

  • numBlockConfirmations (uint64): The number of block confirmations to consider.

Flow:

  1. Convert numBlockConfirmations to an integer numBlockConfirmationsInt.
  2. Check if the length of t.blocks (slice of block numbers) is greater than numBlockConfirmationsInt.
  3. If it is, return a sub-slice of t.blocks from the beginning to the length of t.blocks minus numBlockConfirmationsInt.
  4. If it is not, return nil.

Outputs:

  • A slice of uint64 representing the block numbers of confirmed blocks.

func (*TrackerBlockContainer) IsBlockFromThePastLocked

func (t *TrackerBlockContainer) IsBlockFromThePastLocked(block *ethgo.Block) bool

IsBlockFromThePastLocked checks if a block is from the past, meaning it has a number less or equal than the last processed confirmed block.

Inputs: - block (ethgo.Block): The latest block of the tracked chain.

Outputs: - bool: A boolean value indicating that the tracker last processed confirmed block is more recent than the given block.

func (*TrackerBlockContainer) IsOutOfSync

func (t *TrackerBlockContainer) IsOutOfSync(block *ethgo.Block) bool

IsOutOfSync checks if tracker is out of sync with the tracked chain. Tracker is out of sync with the tracked chain if these conditions are met:

  • latest block from chain has higher number than the last tracked block
  • its parent doesn't exist in numToHash map
  • its parent hash doesn't match with the hash of the given parent block we tracked, meaning, a reorg happened

Inputs: - block (ethgo.Block): The latest block of the tracked chain.

Outputs: - outOfSync (bool): A boolean value indicating if the tracker is out of sync (true) or not (false).

func (*TrackerBlockContainer) LastCachedBlock

func (t *TrackerBlockContainer) LastCachedBlock() uint64

LastCachedBlock returns the block number of the last cached block for processing

Example Usage:

t := NewTrackerBlockContainer(1)
t.AddBlock(&ethgo.Block{Number: 1, Hash: "hash1"})
t.AddBlock(&ethgo.Block{Number: 2, Hash: "hash2"})
t.AddBlock(&ethgo.Block{Number: 3, Hash: "hash3"})

lastCachedBlock := t.LastCachedBlock()
fmt.Println(lastCachedBlock) // Output: 3

Outputs:

The output is a uint64 value representing the block number of the last cached block.

func (*TrackerBlockContainer) LastProcessedBlock

func (t *TrackerBlockContainer) LastProcessedBlock() uint64

LastProcessedBlockLocked returns number of last processed block for logs Function acquires the read lock before accessing the lastProcessedConfirmedBlock field

func (*TrackerBlockContainer) LastProcessedBlockLocked

func (t *TrackerBlockContainer) LastProcessedBlockLocked() uint64

LastProcessedBlockLocked returns number of last processed block for logs Function assumes that the read or write lock is already acquired before accessing the lastProcessedConfirmedBlock field

func (*TrackerBlockContainer) ReleaseWriteLock

func (t *TrackerBlockContainer) ReleaseWriteLock()

ReleaseWriteLock releases the write lock on the TrackerBlockContainer

func (*TrackerBlockContainer) RemoveAllAfterParentOf

func (t *TrackerBlockContainer) RemoveAllAfterParentOf(block *ethgo.Block)

RemoveAllAfterParentOf finds the parent of the given block and removes all subsequent blocks from the memory container.

Inputs: - block (*ethgo.Block): The Ethereum block whose parent's position will be used as a reference.

func (*TrackerBlockContainer) RemoveBlocks

func (t *TrackerBlockContainer) RemoveBlocks(from, last uint64) error

RemoveBlocks removes processed blocks from cached maps, and updates the lastProcessedConfirmedBlock variable, to the last processed block.

Inputs: - from (uint64): The starting block number to remove. - last (uint64): The ending block number to remove.

Returns:

  • nil if removal is successful
  • An error if from block is greater than the last, if given range of blocks was already processed and removed, if the last block could not be found in cached blocks, or if we are trying to do a non sequential removal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL