-
Notifications
You must be signed in to change notification settings - Fork 237
feat(l1): introduce SettlementLayer and EthMessagingClient abstractions #3738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
brbrr
wants to merge
15
commits into
main
Choose a base branch
from
feat/l1-settlement-geth
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
1ce6597
feat(l1,rpc/rpccore): introduce SettlementLayer + EthMessagingClient …
brbrr a8a58b7
feat(l1/geth): geth-backed SettlementLayer adapter
brbrr c6abec5
refactor(l1): migrate l1.Client and callers to SettlementLayer
brbrr 204ca9a
refactor(l1): delete dead EthSubscriber-era bindings and receipt adapter
brbrr 934d723
address feedback
brbrr 727091c
comments cleanup
brbrr 1c9efa4
chore(l1/geth_settlement): Simplify StateUpdate production
brbrr a832792
chore: relocate Subscription, fix l1 metrics registration
brbrr d6617be
chore: trim some comments
brbrr 1c464ae
chore: add missing file and fix linter issues
brbrr ed3d75d
chore: error messages and unused rpcClient
brbrr 9e85c46
chore: rename Settlement -> L1StateProvider
brbrr 4a4d733
chore: address last bits of feedback
brbrr a5ce15a
Merge branch 'main' into feat/l1-settlement-geth
brbrr b66a9c5
fix bad rebase
brbrr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| // NOTE: This export file should stay as is and no other additions can be done to it. | ||
| // The goal is to eventually remove each of the methods in this file by rewriting the | ||
| // tests to use the public API only. | ||
| package l1 | ||
|
|
||
| import ( | ||
| "context" | ||
| ) | ||
|
|
||
| // Exposes package-private surface to the external l1_test package. The | ||
| // tests live there to avoid a circular import: l1 > mocks > l1. | ||
|
|
||
| // Deprecated: use the public API instead. | ||
| func (c *Client) SetL1StateProvider(s L1StateProvider) { c.provider = s } | ||
|
|
||
| // Deprecated: use the public API instead. | ||
| func (c *Client) NonFinalisedLogs() map[uint64]*StateUpdate { | ||
| return c.nonFinalisedLogs | ||
| } | ||
|
|
||
| // Deprecated: use the public API instead. | ||
| func (c *Client) SubscribeToUpdates(ctx context.Context, ch chan *StateUpdate) Subscription { | ||
| return c.subscribeToUpdates(ctx, ch) | ||
| } | ||
|
|
||
| // Deprecated: use the public API instead. | ||
| func (c *Client) FinalisedHeight(ctx context.Context) (uint64, bool) { | ||
| return c.finalisedHeight(ctx) | ||
| } |
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| package l1 | ||
|
|
||
| import ( | ||
| "errors" | ||
| "math/big" | ||
| "sync/atomic" | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/NethermindEth/juno/core/felt" | ||
| "github.com/NethermindEth/juno/l1/geth/contract" | ||
| "github.com/ethereum/go-ethereum/core/types" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| // fakeEventSub is a minimal event.Subscription that lets the test drive | ||
| // error delivery and observe Unsubscribe. | ||
| type fakeEventSub struct { | ||
| errCh chan error | ||
| unsubbed atomic.Bool | ||
| } | ||
|
|
||
| func newFakeEventSub() *fakeEventSub { | ||
| return &fakeEventSub{errCh: make(chan error, 1)} | ||
| } | ||
|
|
||
| func (f *fakeEventSub) Err() <-chan error { return f.errCh } | ||
|
|
||
| func (f *fakeEventSub) Unsubscribe() { | ||
| if f.unsubbed.CompareAndSwap(false, true) { | ||
| close(f.errCh) | ||
| } | ||
| } | ||
|
|
||
| // newForwarderForTest wires forwardStateUpdates to a fake inner subscription | ||
| // and returns the resulting Subscription along with the writable raw | ||
| // channel the test feeds contract events into. | ||
| func newForwarderForTest( | ||
| sink chan *StateUpdate, inner *fakeEventSub, | ||
| ) (Subscription, chan *contract.StarknetLogStateUpdate) { | ||
| raw := make(chan *contract.StarknetLogStateUpdate, 1) | ||
| sub := forwardStateUpdates(inner, raw, sink) | ||
| return sub, raw | ||
| } | ||
|
|
||
| func sampleStarknetLogStateUpdate() *contract.StarknetLogStateUpdate { | ||
| return &contract.StarknetLogStateUpdate{ | ||
| BlockNumber: big.NewInt(42), | ||
| BlockHash: big.NewInt(0xabc), | ||
| GlobalRoot: big.NewInt(0xdef), | ||
| Raw: types.Log{ | ||
| BlockNumber: 99, | ||
| Removed: false, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| // expectErrChClosed asserts that Err() is closed (drained of any pending | ||
| // value, then EOF) within the deadline. event.NewSubscription closes the | ||
| // error channel exactly once after the producer returns, so a closed Err() | ||
| // proves the forwarding goroutine has torn down. | ||
| func expectErrChClosed(t *testing.T, ch <-chan error) { | ||
| t.Helper() | ||
| deadline := time.After(2 * time.Second) | ||
| for { | ||
| select { | ||
| case _, ok := <-ch: | ||
| if !ok { | ||
| return | ||
| } | ||
| case <-deadline: | ||
| t.Fatal("timed out waiting for Err() to close") | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func TestForwardStateUpdates_NormalForward(t *testing.T) { | ||
| sink := make(chan *StateUpdate, 1) | ||
| inner := newFakeEventSub() | ||
| sub, raw := newForwarderForTest(sink, inner) | ||
| t.Cleanup(sub.Unsubscribe) | ||
|
|
||
| ev := sampleStarknetLogStateUpdate() | ||
| raw <- ev | ||
|
|
||
| select { | ||
| case got := <-sink: | ||
| require.NotNil(t, got) | ||
| assert.Equal(t, uint64(42), got.L2BlockNumber) | ||
| assert.Equal(t, uint64(99), got.L1RefHeight) | ||
| assert.False(t, got.Removed) | ||
| assert.Equal(t, new(felt.Felt).SetBigInt(ev.BlockHash), got.L2BlockHash) | ||
| assert.Equal(t, new(felt.Felt).SetBigInt(ev.GlobalRoot), got.StateRoot) | ||
| case <-time.After(2 * time.Second): | ||
| t.Fatal("event not forwarded to sink") | ||
| } | ||
|
|
||
| // Err() should still be open while the forwarder is running. | ||
| select { | ||
| case _, ok := <-sub.Err(): | ||
| t.Fatalf("Err() unexpectedly closed/delivered while running (ok=%v)", ok) | ||
| default: | ||
| } | ||
| } | ||
|
|
||
| func TestForwardStateUpdates_InnerErrorDeliversAndCloses(t *testing.T) { | ||
| sink := make(chan *StateUpdate, 1) | ||
| inner := newFakeEventSub() | ||
| sub, _ := newForwarderForTest(sink, inner) | ||
|
|
||
| cause := errors.New("upstream gone") | ||
| inner.errCh <- cause | ||
|
|
||
| select { | ||
| case err := <-sub.Err(): | ||
| require.ErrorIs(t, err, cause) | ||
| case <-time.After(2 * time.Second): | ||
| t.Fatal("Err() did not deliver the cause") | ||
| } | ||
| // After the cause is delivered the channel must close — a second | ||
| // receive yields (zero, !ok). | ||
| select { | ||
| case err, ok := <-sub.Err(): | ||
| assert.False(t, ok, "Err() should be closed after delivering cause") | ||
| assert.NoError(t, err) | ||
| case <-time.After(2 * time.Second): | ||
| t.Fatal("Err() not closed after delivering cause") | ||
| } | ||
| } | ||
|
|
||
| func TestForwardStateUpdates_UnsubscribeExitsGoroutine(t *testing.T) { | ||
| sink := make(chan *StateUpdate, 1) | ||
| inner := newFakeEventSub() | ||
| sub, _ := newForwarderForTest(sink, inner) | ||
|
|
||
| sub.Unsubscribe() | ||
| assert.True(t, inner.unsubbed.Load(), "inner subscription should be Unsubscribed") | ||
| expectErrChClosed(t, sub.Err()) | ||
| } | ||
|
|
||
| func TestForwardStateUpdates_SinkStalledThenUnsubscribe(t *testing.T) { | ||
| // Unbuffered sink, never drained: if the forwarding loop reaches the | ||
| // `case sink <- ...` branch it will block there. Unsubscribe() must | ||
| // unblock it via the <-quit arm of the inner select. | ||
| sink := make(chan *StateUpdate) | ||
| inner := newFakeEventSub() | ||
| sub, raw := newForwarderForTest(sink, inner) | ||
|
|
||
| raw <- sampleStarknetLogStateUpdate() | ||
| sub.Unsubscribe() | ||
|
|
||
| expectErrChClosed(t, sub.Err()) | ||
| assert.True(t, inner.unsubbed.Load()) | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.