From 4e0d72bfd4973b11ad9087285e21fb407aab4fe6 Mon Sep 17 00:00:00 2001 From: Sambhav Jain <136801346+DarkLord017@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:23:29 +0530 Subject: [PATCH 1/6] Refactor consensus/rpc/consensus_rpc.go --- consensus/rpc/consensus_rpc.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/consensus/rpc/consensus_rpc.go b/consensus/rpc/consensus_rpc.go index 22dc00e..255d939 100644 --- a/consensus/rpc/consensus_rpc.go +++ b/consensus/rpc/consensus_rpc.go @@ -2,6 +2,7 @@ package rpc import ( "github.com/BlocSoc-iitr/selene/consensus/consensus_core" + "github.com/BlocSoc-iitr/selene/utils" ) // return types not mention and oarameters as well @@ -15,5 +16,10 @@ type ConsensusRpc interface { } func NewConsensusRpc(rpc string) ConsensusRpc { - return NewNimbusRpc(rpc) + if utils.IsURL(rpc) { + return NewNimbusRpc(rpc) + } else { + return NewMockRpc(rpc) + } + } From af1cf3c4e621730709fb15240dff59361101a359 Mon Sep 17 00:00:00 2001 From: Sambhav Jain <136801346+DarkLord017@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:24:13 +0530 Subject: [PATCH 2/6] Refactor mock_rpc.go --- consensus/rpc/mock_rpc.go | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/consensus/rpc/mock_rpc.go b/consensus/rpc/mock_rpc.go index 971f381..1801a64 100644 --- a/consensus/rpc/mock_rpc.go +++ b/consensus/rpc/mock_rpc.go @@ -5,31 +5,33 @@ package rpc import ( "encoding/json" "fmt" - "github.com/BlocSoc-iitr/selene/consensus/consensus_core" "os" "path/filepath" + + "github.com/BlocSoc-iitr/selene/consensus/consensus_core" ) type MockRpc struct { testdata string } + func NewMockRpc(path string) *MockRpc { return &MockRpc{ testdata: path, } } -func (m *MockRpc) GetBootstrap(block_root []byte) (*consensus_core.Bootstrap, error) { +func (m *MockRpc) GetBootstrap(block_root [32]byte) (consensus_core.Bootstrap, error) { path := filepath.Join(m.testdata, "bootstrap.json") res, err := os.ReadFile(path) if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) + return consensus_core.Bootstrap{}, fmt.Errorf("failed to read file: %w", err) } var bootstrap BootstrapResponse err = json.Unmarshal(res, &bootstrap) if err != nil { - return &consensus_core.Bootstrap{}, fmt.Errorf("bootstrap error: %w", err) + return consensus_core.Bootstrap{}, fmt.Errorf("bootstrap error: %w", err) } - return &bootstrap.Data, nil + return bootstrap.Data, nil } func (m *MockRpc) GetUpdates(period uint64, count uint8) ([]consensus_core.Update, error) { path := filepath.Join(m.testdata, "updates.json") @@ -48,44 +50,44 @@ func (m *MockRpc) GetUpdates(period uint64, count uint8) ([]consensus_core.Updat } return updates, nil } -func (m *MockRpc) GetFinalityUpdate() (*consensus_core.FinalityUpdate, error) { +func (m *MockRpc) GetFinalityUpdate() (consensus_core.FinalityUpdate, error) { path := filepath.Join(m.testdata, "finality.json") res, err := os.ReadFile(path) if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) + return consensus_core.FinalityUpdate{}, fmt.Errorf("failed to read file: %w", err) } var finality FinalityUpdateResponse err = json.Unmarshal(res, &finality) if err != nil { - return &consensus_core.FinalityUpdate{}, fmt.Errorf("finality update error: %w", err) + return consensus_core.FinalityUpdate{}, fmt.Errorf("finality update error: %w", err) } - return &finality.Data, nil + return finality.Data, nil } -func (m *MockRpc) GetOptimisticUpdate() (*consensus_core.OptimisticUpdate, error) { +func (m *MockRpc) GetOptimisticUpdate() (consensus_core.OptimisticUpdate, error) { path := filepath.Join(m.testdata, "optimistic.json") res, err := os.ReadFile(path) if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) + return consensus_core.OptimisticUpdate{}, fmt.Errorf("failed to read file: %w", err) } var optimistic OptimisticUpdateResponse err = json.Unmarshal(res, &optimistic) if err != nil { - return &consensus_core.OptimisticUpdate{}, fmt.Errorf("optimistic update error: %w", err) + return consensus_core.OptimisticUpdate{}, fmt.Errorf("optimistic update error: %w", err) } - return &optimistic.Data, nil + return optimistic.Data, nil } -func (m *MockRpc) GetBlock(slot uint64) (*consensus_core.BeaconBlock, error) { +func (m *MockRpc) GetBlock(slot uint64) (consensus_core.BeaconBlock, error) { path := filepath.Join(m.testdata, fmt.Sprintf("blocks/%d.json", slot)) res, err := os.ReadFile(path) if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) + return consensus_core.BeaconBlock{}, fmt.Errorf("failed to read file: %w", err) } var block BeaconBlockResponse err = json.Unmarshal(res, &block) if err != nil { - return nil, err + return consensus_core.BeaconBlock{}, err } - return &block.Data.Message, nil + return block.Data.Message, nil } func (m *MockRpc) ChainId() (uint64, error) { return 0, fmt.Errorf("not implemented") From 9fa9710752b8e2ab31d46fcf3a1b69574be60f6b Mon Sep 17 00:00:00 2001 From: Sambhav Jain <136801346+DarkLord017@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:24:40 +0530 Subject: [PATCH 3/6] Refactor nimbus_rpc.go From ea9cca16a296d914e3c0cd60cd44bf45879aa29c Mon Sep 17 00:00:00 2001 From: Sambhav Jain <136801346+DarkLord017@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:25:03 +0530 Subject: [PATCH 4/6] Refactor mock_rpc_test.go --- consensus/rpc/mock_rpc_test.go | 260 +++++++++++++++------------------ 1 file changed, 114 insertions(+), 146 deletions(-) diff --git a/consensus/rpc/mock_rpc_test.go b/consensus/rpc/mock_rpc_test.go index b371a54..8eaf833 100644 --- a/consensus/rpc/mock_rpc_test.go +++ b/consensus/rpc/mock_rpc_test.go @@ -1,163 +1,131 @@ package rpc + import ( "encoding/json" - "os" - "path/filepath" + "fmt" + "net/http" + "net/http/httptest" "testing" "github.com/BlocSoc-iitr/selene/consensus/consensus_core" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) -func TestNewMockRpc(t *testing.T) { - path := "/tmp/testdata" - mockRpc := NewMockRpc(path) - if mockRpc.testdata != path { - t.Errorf("Expected testdata path to be %s, got %s", path, mockRpc.testdata) - } + +func TestNewNimbusRpc(t *testing.T) { + rpcURL := "http://example.com" + nimbusRpc := NewNimbusRpc(rpcURL) + assert.Equal(t, rpcURL, nimbusRpc.rpc) } -func TestGetBootstrap(t *testing.T) { - tempDir, err := os.MkdirTemp("", "mock_rpc_test") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - defer os.RemoveAll(tempDir) - mockBootstrap := BootstrapResponse{ - Data: consensus_core.Bootstrap{ - Header: consensus_core.Header{ - Slot: 1000, +func TestNimbusGetBootstrap(t *testing.T) { + blockRoot := [32]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} + expectedPath := fmt.Sprintf("/eth/v1/beacon/light_client/bootstrap/0x%x", blockRoot) + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, expectedPath, r.URL.Path) + response := BootstrapResponse{ + Data: consensus_core.Bootstrap{ + Header: consensus_core.Header{ + Slot: 1000, + }, }, - }, - } - bootstrapJSON, _ := json.Marshal(mockBootstrap) - err = os.WriteFile(filepath.Join(tempDir, "bootstrap.json"), bootstrapJSON, 0644) - if err != nil { - t.Fatalf("Failed to write mock bootstrap file: %v", err) - } - mockRpc := NewMockRpc(tempDir) - bootstrap, err := mockRpc.GetBootstrap([]byte{}) - if err != nil { - t.Fatalf("GetBootstrap failed: %v", err) - } - if bootstrap.Header.Slot != 1000 { - t.Errorf("Expected bootstrap slot to be 1000, got %d", bootstrap.Header.Slot) - } + } + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) + defer server.Close() + nimbusRpc := NewNimbusRpc(server.URL) + bootstrap, err := nimbusRpc.GetBootstrap(blockRoot) + assert.NoError(t, err) + assert.Equal(t, uint64(1000), bootstrap.Header.Slot) } -func TestGetUpdates(t *testing.T) { - tempDir, err := os.MkdirTemp("", "mock_rpc_test") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - defer os.RemoveAll(tempDir) - mockUpdates := UpdateResponse{ - {Data: consensus_core.Update{SignatureSlot: 1}}, - {Data: consensus_core.Update{SignatureSlot: 2}}, - } - updatesJSON, _ := json.Marshal(mockUpdates) - err = os.WriteFile(filepath.Join(tempDir, "updates.json"), updatesJSON, 0644) - if err != nil { - t.Fatalf("Failed to write mock updates file: %v", err) - } - mockRpc := NewMockRpc(tempDir) - updates, err := mockRpc.GetUpdates(1, 2) - if err != nil { - t.Fatalf("GetUpdates failed: %v", err) - } - if len(updates) != 2 { - t.Errorf("Expected 2 updates, got %d", len(updates)) - } - if updates[0].SignatureSlot != 1 || updates[1].SignatureSlot != 2 { - t.Errorf("Unexpected update signature slots") - } +func TestNimbusGetUpdates(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/eth/v1/beacon/light_client/updates", r.URL.Path) + assert.Equal(t, "start_period=1000&count=5", r.URL.RawQuery) + response := UpdateResponse{ + {Data: consensus_core.Update{AttestedHeader: consensus_core.Header{Slot: 1000}}}, + {Data: consensus_core.Update{AttestedHeader: consensus_core.Header{Slot: 1001}}}, + } + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) + defer server.Close() + nimbusRpc := NewNimbusRpc(server.URL) + updates, err := nimbusRpc.GetUpdates(1000, 5) + assert.NoError(t, err) + assert.Len(t, updates, 2) + assert.Equal(t, uint64(1000), updates[0].AttestedHeader.Slot) + assert.Equal(t, uint64(1001), updates[1].AttestedHeader.Slot) } -func TestGetFinalityUpdate(t *testing.T) { - tempDir, err := os.MkdirTemp("", "mock_rpc_test") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - defer os.RemoveAll(tempDir) - mockFinality := FinalityUpdateResponse{ - Data: consensus_core.FinalityUpdate{ - FinalizedHeader: consensus_core.Header{ - Slot: 2000, +func TestNimbusGetFinalityUpdate(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/eth/v1/beacon/light_client/finality_update", r.URL.Path) + response := FinalityUpdateResponse{ + Data: consensus_core.FinalityUpdate{ + FinalizedHeader: consensus_core.Header{ + Slot: 2000, + }, }, - }, - } - finalityJSON, _ := json.Marshal(mockFinality) - err = os.WriteFile(filepath.Join(tempDir, "finality.json"), finalityJSON, 0644) - if err != nil { - t.Fatalf("Failed to write mock finality file: %v", err) - } - mockRpc := NewMockRpc(tempDir) - finality, err := mockRpc.GetFinalityUpdate() - if err != nil { - t.Fatalf("GetFinalityUpdate failed: %v", err) - } - if finality.FinalizedHeader.Slot != 2000 { - t.Errorf("Expected finality slot to be 2000, got %d", finality.FinalizedHeader.Slot) - } + } + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) + defer server.Close() + nimbusRpc := NewNimbusRpc(server.URL) + finalityUpdate, err := nimbusRpc.GetFinalityUpdate() + assert.NoError(t, err) + assert.Equal(t, uint64(2000), finalityUpdate.FinalizedHeader.Slot) } -func TestGetOptimisticUpdate(t *testing.T) { - tempDir, err := os.MkdirTemp("", "mock_rpc_test") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - defer os.RemoveAll(tempDir) - mockOptimistic := OptimisticUpdateResponse{ - Data: consensus_core.OptimisticUpdate{ - SignatureSlot: 3000, - }, - } - optimisticJSON, _ := json.Marshal(mockOptimistic) - err = os.WriteFile(filepath.Join(tempDir, "optimistic.json"), optimisticJSON, 0644) - if err != nil { - t.Fatalf("Failed to write mock optimistic file: %v", err) - } - mockRpc := NewMockRpc(tempDir) - optimistic, err := mockRpc.GetOptimisticUpdate() - if err != nil { - t.Fatalf("GetOptimisticUpdate failed: %v", err) - } - if optimistic.SignatureSlot != 3000 { - t.Errorf("Expected optimistic signature slot to be 3000, got %d", optimistic.SignatureSlot) - } +func TestNimbusGetOptimisticUpdate(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/eth/v1/beacon/light_client/optimistic_update", r.URL.Path) + response := OptimisticUpdateResponse{ + Data: consensus_core.OptimisticUpdate{ + SignatureSlot: 3000, + }, + } + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) + defer server.Close() + nimbusRpc := NewNimbusRpc(server.URL) + optimisticUpdate, err := nimbusRpc.GetOptimisticUpdate() + assert.NoError(t, err) + assert.Equal(t, uint64(3000), optimisticUpdate.SignatureSlot) } -func TestGetBlock(t *testing.T) { - tempDir, err := os.MkdirTemp("", "mock_rpc_test") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - defer os.RemoveAll(tempDir) - blocksDir := filepath.Join(tempDir, "blocks") - err = os.Mkdir(blocksDir, 0755) - if err != nil { - t.Fatalf("Failed to create blocks directory: %v", err) - } - mockBlock := BeaconBlockResponse{ - Data: struct { - Message consensus_core.BeaconBlock - }{ - Message: consensus_core.BeaconBlock{ - Slot: 4000, +func TestNimbusGetBlock(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/eth/v2/beacon/blocks/4000", r.URL.Path) + response := BeaconBlockResponse{ + Data: BeaconBlockData{ + Message: consensus_core.BeaconBlock{ + Slot: 4000, + }, }, - }, - } - blockJSON, _ := json.Marshal(mockBlock) - err = os.WriteFile(filepath.Join(blocksDir, "4000.json"), blockJSON, 0644) - if err != nil { - t.Fatalf("Failed to write mock block file: %v", err) - } - mockRpc := NewMockRpc(tempDir) - block, err := mockRpc.GetBlock(4000) - if err != nil { - t.Fatalf("GetBlock failed: %v", err) - } - if block.Slot != 4000 { - t.Errorf("Expected block slot to be 4000, got %d", block.Slot) - } + } + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) + defer server.Close() + nimbusRpc := NewNimbusRpc(server.URL) + block, err := nimbusRpc.GetBlock(4000) + assert.NoError(t, err) + assert.Equal(t, uint64(4000), block.Slot) } -func TestChainId(t *testing.T) { - mockRpc := NewMockRpc("/tmp/testdata") - _, err := mockRpc.ChainId() - if err == nil || err.Error() != "not implemented" { - t.Errorf("Expected 'not implemented' error, got %v", err) - } +func TestNimbusChainId(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, "/eth/v1/config/spec", r.URL.Path) + response := SpecResponse{ + Data: Spec{ + ChainId: 5000, + }, + } + err := json.NewEncoder(w).Encode(response) + require.NoError(t, err) + })) + defer server.Close() + nimbusRpc := NewNimbusRpc(server.URL) + chainId, err := nimbusRpc.ChainId() + assert.NoError(t, err) + assert.Equal(t, uint64(5000), chainId) } From f0f0f368397c60c05b200307c1d93e370ace89ce Mon Sep 17 00:00:00 2001 From: Sambhav Jain <136801346+DarkLord017@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:26:31 +0530 Subject: [PATCH 5/6] Refactor RPC module --- utils/utils.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/utils.go b/utils/utils.go index c44317c..e2f614a 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -2,7 +2,7 @@ package utils import ( "encoding/hex" - + "net/url" "strings" "bytes" @@ -279,3 +279,7 @@ func BranchToNodes(branch []consensus_core.Bytes32) ([][]byte, error) { } return nodes, nil } +func IsURL(str string) bool { + u, err := url.Parse(str) + return err == nil && u.Scheme != "" && u.Host != "" +} From 94f35d5e51819d721021289cb2fdc96f01113157 Mon Sep 17 00:00:00 2001 From: Sambhav Jain <136801346+DarkLord017@users.noreply.github.com> Date: Sat, 28 Sep 2024 02:28:27 +0530 Subject: [PATCH 6/6] Update mock_rpc_test.go --- consensus/rpc/mock_rpc_test.go | 258 +++++++++++++++++++-------------- 1 file changed, 146 insertions(+), 112 deletions(-) diff --git a/consensus/rpc/mock_rpc_test.go b/consensus/rpc/mock_rpc_test.go index 8eaf833..550080e 100644 --- a/consensus/rpc/mock_rpc_test.go +++ b/consensus/rpc/mock_rpc_test.go @@ -2,130 +2,164 @@ package rpc import ( "encoding/json" - "fmt" - "net/http" - "net/http/httptest" + "os" + "path/filepath" "testing" "github.com/BlocSoc-iitr/selene/consensus/consensus_core" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) -func TestNewNimbusRpc(t *testing.T) { - rpcURL := "http://example.com" - nimbusRpc := NewNimbusRpc(rpcURL) - assert.Equal(t, rpcURL, nimbusRpc.rpc) +func TestNewMockRpc(t *testing.T) { + path := "/tmp/testdata" + mockRpc := NewMockRpc(path) + if mockRpc.testdata != path { + t.Errorf("Expected testdata path to be %s, got %s", path, mockRpc.testdata) + } } -func TestNimbusGetBootstrap(t *testing.T) { - blockRoot := [32]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - expectedPath := fmt.Sprintf("/eth/v1/beacon/light_client/bootstrap/0x%x", blockRoot) - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, expectedPath, r.URL.Path) - response := BootstrapResponse{ - Data: consensus_core.Bootstrap{ - Header: consensus_core.Header{ - Slot: 1000, - }, +func TestGetBootstrap(t *testing.T) { + tempDir, err := os.MkdirTemp("", "mock_rpc_test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + mockBootstrap := BootstrapResponse{ + Data: consensus_core.Bootstrap{ + Header: consensus_core.Header{ + Slot: 1000, }, - } - err := json.NewEncoder(w).Encode(response) - require.NoError(t, err) - })) - defer server.Close() - nimbusRpc := NewNimbusRpc(server.URL) - bootstrap, err := nimbusRpc.GetBootstrap(blockRoot) - assert.NoError(t, err) - assert.Equal(t, uint64(1000), bootstrap.Header.Slot) + }, + } + bootstrapJSON, _ := json.Marshal(mockBootstrap) + err = os.WriteFile(filepath.Join(tempDir, "bootstrap.json"), bootstrapJSON, 0644) + if err != nil { + t.Fatalf("Failed to write mock bootstrap file: %v", err) + } + mockRpc := NewMockRpc(tempDir) + bootstrap, err := mockRpc.GetBootstrap([32]byte{}) + if err != nil { + t.Fatalf("GetBootstrap failed: %v", err) + } + if bootstrap.Header.Slot != 1000 { + t.Errorf("Expected bootstrap slot to be 1000, got %d", bootstrap.Header.Slot) + } } -func TestNimbusGetUpdates(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/eth/v1/beacon/light_client/updates", r.URL.Path) - assert.Equal(t, "start_period=1000&count=5", r.URL.RawQuery) - response := UpdateResponse{ - {Data: consensus_core.Update{AttestedHeader: consensus_core.Header{Slot: 1000}}}, - {Data: consensus_core.Update{AttestedHeader: consensus_core.Header{Slot: 1001}}}, - } - err := json.NewEncoder(w).Encode(response) - require.NoError(t, err) - })) - defer server.Close() - nimbusRpc := NewNimbusRpc(server.URL) - updates, err := nimbusRpc.GetUpdates(1000, 5) - assert.NoError(t, err) - assert.Len(t, updates, 2) - assert.Equal(t, uint64(1000), updates[0].AttestedHeader.Slot) - assert.Equal(t, uint64(1001), updates[1].AttestedHeader.Slot) +func TestGetUpdates(t *testing.T) { + tempDir, err := os.MkdirTemp("", "mock_rpc_test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + mockUpdates := UpdateResponse{ + {Data: consensus_core.Update{SignatureSlot: 1}}, + {Data: consensus_core.Update{SignatureSlot: 2}}, + } + updatesJSON, _ := json.Marshal(mockUpdates) + err = os.WriteFile(filepath.Join(tempDir, "updates.json"), updatesJSON, 0644) + if err != nil { + t.Fatalf("Failed to write mock updates file: %v", err) + } + mockRpc := NewMockRpc(tempDir) + updates, err := mockRpc.GetUpdates(1, 2) + if err != nil { + t.Fatalf("GetUpdates failed: %v", err) + } + if len(updates) != 2 { + t.Errorf("Expected 2 updates, got %d", len(updates)) + } + if updates[0].SignatureSlot != 1 || updates[1].SignatureSlot != 2 { + t.Errorf("Unexpected update signature slots") + } } -func TestNimbusGetFinalityUpdate(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/eth/v1/beacon/light_client/finality_update", r.URL.Path) - response := FinalityUpdateResponse{ - Data: consensus_core.FinalityUpdate{ - FinalizedHeader: consensus_core.Header{ - Slot: 2000, - }, +func TestGetFinalityUpdate(t *testing.T) { + tempDir, err := os.MkdirTemp("", "mock_rpc_test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + mockFinality := FinalityUpdateResponse{ + Data: consensus_core.FinalityUpdate{ + FinalizedHeader: consensus_core.Header{ + Slot: 2000, }, - } - err := json.NewEncoder(w).Encode(response) - require.NoError(t, err) - })) - defer server.Close() - nimbusRpc := NewNimbusRpc(server.URL) - finalityUpdate, err := nimbusRpc.GetFinalityUpdate() - assert.NoError(t, err) - assert.Equal(t, uint64(2000), finalityUpdate.FinalizedHeader.Slot) + }, + } + finalityJSON, _ := json.Marshal(mockFinality) + err = os.WriteFile(filepath.Join(tempDir, "finality.json"), finalityJSON, 0644) + if err != nil { + t.Fatalf("Failed to write mock finality file: %v", err) + } + mockRpc := NewMockRpc(tempDir) + finality, err := mockRpc.GetFinalityUpdate() + if err != nil { + t.Fatalf("GetFinalityUpdate failed: %v", err) + } + if finality.FinalizedHeader.Slot != 2000 { + t.Errorf("Expected finality slot to be 2000, got %d", finality.FinalizedHeader.Slot) + } } -func TestNimbusGetOptimisticUpdate(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/eth/v1/beacon/light_client/optimistic_update", r.URL.Path) - response := OptimisticUpdateResponse{ - Data: consensus_core.OptimisticUpdate{ - SignatureSlot: 3000, - }, - } - err := json.NewEncoder(w).Encode(response) - require.NoError(t, err) - })) - defer server.Close() - nimbusRpc := NewNimbusRpc(server.URL) - optimisticUpdate, err := nimbusRpc.GetOptimisticUpdate() - assert.NoError(t, err) - assert.Equal(t, uint64(3000), optimisticUpdate.SignatureSlot) +func TestGetOptimisticUpdate(t *testing.T) { + tempDir, err := os.MkdirTemp("", "mock_rpc_test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + mockOptimistic := OptimisticUpdateResponse{ + Data: consensus_core.OptimisticUpdate{ + SignatureSlot: 3000, + }, + } + optimisticJSON, _ := json.Marshal(mockOptimistic) + err = os.WriteFile(filepath.Join(tempDir, "optimistic.json"), optimisticJSON, 0644) + if err != nil { + t.Fatalf("Failed to write mock optimistic file: %v", err) + } + mockRpc := NewMockRpc(tempDir) + optimistic, err := mockRpc.GetOptimisticUpdate() + if err != nil { + t.Fatalf("GetOptimisticUpdate failed: %v", err) + } + if optimistic.SignatureSlot != 3000 { + t.Errorf("Expected optimistic signature slot to be 3000, got %d", optimistic.SignatureSlot) + } } -func TestNimbusGetBlock(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/eth/v2/beacon/blocks/4000", r.URL.Path) - response := BeaconBlockResponse{ - Data: BeaconBlockData{ - Message: consensus_core.BeaconBlock{ - Slot: 4000, - }, +func TestGetBlock(t *testing.T) { + tempDir, err := os.MkdirTemp("", "mock_rpc_test") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + defer os.RemoveAll(tempDir) + blocksDir := filepath.Join(tempDir, "blocks") + err = os.Mkdir(blocksDir, 0755) + if err != nil { + t.Fatalf("Failed to create blocks directory: %v", err) + } + mockBlock := BeaconBlockResponse{ + Data: struct { + Message consensus_core.BeaconBlock + }{ + Message: consensus_core.BeaconBlock{ + Slot: 4000, }, - } - err := json.NewEncoder(w).Encode(response) - require.NoError(t, err) - })) - defer server.Close() - nimbusRpc := NewNimbusRpc(server.URL) - block, err := nimbusRpc.GetBlock(4000) - assert.NoError(t, err) - assert.Equal(t, uint64(4000), block.Slot) + }, + } + blockJSON, _ := json.Marshal(mockBlock) + err = os.WriteFile(filepath.Join(blocksDir, "4000.json"), blockJSON, 0644) + if err != nil { + t.Fatalf("Failed to write mock block file: %v", err) + } + mockRpc := NewMockRpc(tempDir) + block, err := mockRpc.GetBlock(4000) + if err != nil { + t.Fatalf("GetBlock failed: %v", err) + } + if block.Slot != 4000 { + t.Errorf("Expected block slot to be 4000, got %d", block.Slot) + } } -func TestNimbusChainId(t *testing.T) { - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - assert.Equal(t, "/eth/v1/config/spec", r.URL.Path) - response := SpecResponse{ - Data: Spec{ - ChainId: 5000, - }, - } - err := json.NewEncoder(w).Encode(response) - require.NoError(t, err) - })) - defer server.Close() - nimbusRpc := NewNimbusRpc(server.URL) - chainId, err := nimbusRpc.ChainId() - assert.NoError(t, err) - assert.Equal(t, uint64(5000), chainId) +func TestChainId(t *testing.T) { + mockRpc := NewMockRpc("/tmp/testdata") + _, err := mockRpc.ChainId() + if err == nil || err.Error() != "not implemented" { + t.Errorf("Expected 'not implemented' error, got %v", err) + } }