Skip to content

Conversation

@jadepark-dev
Copy link
Collaborator

@jadepark-dev jadepark-dev commented Sep 26, 2025

This PR adds persistent store in TON logpoller, improves query interface, and log ingestion pipeline

Next Steps

  • add TON schema migration file in core
  • initialize postgreSQL database when relayer is started, replacing memory store
  • e2e behavior validation with core TON2EVM and EVM2TON messaging test
  • BOC Header size investigation

@jadepark-dev jadepark-dev changed the title logpoller: core changes and persistent store logpoller: refactors and persistent store Oct 22, 2025

starting_seq_no INTEGER NOT NULL,

created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is the time zone set for TIMESTAMPTZ? Will everything default to UTC?

Comment on lines -59 to -70
hasFilter, err := a.logPoller.HasFilter(ctx, name)
if err != nil {
return fmt.Errorf("failed to check for filter: %w", err)
}
// If filter exists, unregister it first to handle address changes
if hasFilter {
if err := a.logPoller.UnregisterFilter(ctx, name); err != nil {
return fmt.Errorf("failed to unregister logpoller filter: %w", err)
}
}

filter := types.Filter{
Copy link
Collaborator

@ogtownsend ogtownsend Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I see this logic being handled inside of logPoller.ReigsterFilter or elsewhere, but maybe I just can't find it. Is it not needed anymore?

Comment on lines +216 to +230
// Filter at database level using byte-level filtering
// CCIPMessageSent struct layout:
// - Message: 40 bytes at offset 0 (Message struct)
// - DestChainSelector: uint64 (8 bytes) at offset 40
// - SequenceNumber: uint64 (8 bytes) at offset 48
logs, _, _, err := a.logPoller.NewQuery().
WithSource(onrampAddr).
WithEventSig(hash.CRC32(consts.EventNameCCIPMessageSent)).
SkipBytes(40). // Skip to DestChainSelector
FilterBytes(8, query.EQ(binary.BigEndian.AppendUint64(nil, uint64(dest)))).
FilterBytes(8,
query.GTE(binary.BigEndian.AppendUint64(nil, uint64(seqNumRange.Start()))),
query.LTE(binary.BigEndian.AppendUint64(nil, uint64(seqNumRange.End()))),
WithBocBytes(
query.SkipBytes(40),
query.MatchBytes(8, query.WithCondition(binary.BigEndian.AppendUint64(nil, uint64(dest)), primitives.Eq)),
query.MatchBytes(8,
query.WithCondition(binary.BigEndian.AppendUint64(nil, uint64(seqNumRange.Start())), primitives.Gte),
query.WithCondition(binary.BigEndian.AppendUint64(nil, uint64(seqNumRange.End())), primitives.Lte),
),
Copy link
Collaborator

@ogtownsend ogtownsend Nov 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to address in this PR, but I'm wondering if this super exact byte matching query builder logic deserves its own layer in between the accessor and the log poller in the future. It's almost like a separate go-binding layer but for messages/events instead of contract calls. It is product-specific so it makes sense to keep in the accessor for now, but it might be more maintainable as a standalone layer in the long run 🤷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants