Skip to content
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

feat(blobstorage): covering tests for BlockMetaRepo, BlobHashRepo and… #16795

Closed
wants to merge 7 commits into from
Closed
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/taikoxyz/taiko-mono
go 1.21

require (
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/buildkite/terminal-to-html/v3 v3.8.0
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/cenkalti/backoff/v4 v4.3.0
Expand Down Expand Up @@ -35,7 +36,8 @@ require (
gopkg.in/yaml.v3 v3.0.1
gorm.io/datatypes v1.2.0
gorm.io/driver/mysql v1.5.6
gorm.io/gorm v1.25.10
gorm.io/driver/sqlite v1.4.3
gorm.io/gorm v1.25.9
gotest.tools v2.2.0+incompatible
)

Expand Down Expand Up @@ -143,6 +145,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.15 // indirect
github.com/mfridman/interpolate v0.0.2 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
Expand Down Expand Up @@ -173,6 +176,7 @@ require (
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tdewolff/minify/v2 v2.20.14 // indirect
Expand Down
9 changes: 7 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4s
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8=
github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
Expand Down Expand Up @@ -370,6 +372,7 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 h1:rp+c0RAYOWj8l6qbCUTSiRLG/iKnW3K3/QfPPuSsBt4=
Expand Down Expand Up @@ -397,6 +400,7 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/klauspost/compress v1.11.8/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
Expand Down Expand Up @@ -936,9 +940,10 @@ gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.21.3/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.9 h1:wct0gxZIELDk8+ZqF/MVnHLkA1rvYlBWUMv2EdsK1g8=
gorm.io/gorm v1.25.9/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
Expand Down
26 changes: 17 additions & 9 deletions packages/blobstorage/indexer/beaconclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ type GetSpecResponse struct {
Data map[string]string `json:"data"`
}

type GenesisData struct {
GenesisTime string `json:"genesis_time"`
}

type GenesisResponse struct {
Data struct {
GenesisTime string `json:"genesis_time"`
} `json:"data"`
Data GenesisData `json:"data"`
}

type BeaconClient struct {
Expand All @@ -35,13 +37,15 @@ type BeaconClient struct {
secondsPerSlot uint64
}

type BlobData struct {
Index string `json:"index"`
Blob string `json:"blob"`
KzgCommitment string `json:"kzg_commitment"`
KzgCommitmentHex []byte `json:"-"`
}

type BlobsResponse struct {
Data []struct {
Index string `json:"index"`
Blob string `json:"blob"`
KzgCommitment string `json:"kzg_commitment"`
KzgCommitmentHex []byte `json:"-"`
} `json:"data"`
Data []BlobData `json:"data"`
}

func NewBeaconClient(cfg *Config, timeout time.Duration) (*BeaconClient, error) {
Expand Down Expand Up @@ -118,6 +122,10 @@ func (c *BeaconClient) getBlobs(ctx context.Context, blockID uint64) (*BlobsResp
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("server returned non-OK status: %s", response.Status)
}

body, err := io.ReadAll(response.Body)
if err != nil {
return nil, err
Expand Down
204 changes: 204 additions & 0 deletions packages/blobstorage/indexer/beaconclient_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package indexer

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestNewBeaconClient(t *testing.T) {
testCases := []struct {
name string
beaconURL string
genesisResponse interface{}
specResponse interface{}
genesisStatus int
specStatus int
expectedError bool
}{
{
name: "successful NewBeaconClient",
beaconURL: "https://l1beacon.hekla.taiko.xyz",
genesisResponse: GenesisResponse{
Data: GenesisData{GenesisTime: "100"},
},
specResponse: GetSpecResponse{
Data: map[string]string{"SECONDS_PER_SLOT": "10"},
},
genesisStatus: http.StatusOK,
specStatus: http.StatusOK,
expectedError: false,
},
{
name: "error fetching genesis time",
beaconURL: "https://l1beacon.hekla.taiko.xyz",
genesisResponse: "error",
specResponse: GetSpecResponse{
Data: map[string]string{"SECONDS_PER_SLOT": "10"},
},
genesisStatus: http.StatusInternalServerError,
specStatus: http.StatusOK,
expectedError: true,
},
{
name: "error fetching seconds per slot",
beaconURL: "https://l1beacon.hekla.taiko.xyz",
genesisResponse: GenesisResponse{
Data: GenesisData{GenesisTime: "100"},
},
specResponse: "error",
genesisStatus: http.StatusOK,
specStatus: http.StatusInternalServerError,
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
server := httptest.NewServer(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var jsonData []byte
var status int
switch r.URL.Path {
case "/eth/v1/beacon/genesis":
jsonData, _ = json.Marshal(tc.genesisResponse)
status = tc.genesisStatus
case "/eth/v1/config/spec":
jsonData, _ = json.Marshal(tc.specResponse)
status = tc.specStatus
default:
return
}
w.WriteHeader(status)
w.Write(jsonData)
}))
defer server.Close()

cfg := &Config{BeaconURL: server.URL}
client, err := NewBeaconClient(cfg, time.Second*10)

if tc.expectedError {
assert.Error(t, err)
} else {
assert.NotNil(t, client)
}
})
}
}

func TestGetBlobs(t *testing.T) {
testCases := []struct {
name string
blockID uint64
response BlobsResponse
expectedBlobs []BlobData
httpStatus int
expectedError bool
}{
{
name: "successful get blob",
blockID: 123,
response: BlobsResponse{
Data: []BlobData{
{
Index: "1",
Blob: "00001",
KzgCommitment: "0x83ae1d",
},
},
},
expectedBlobs: []BlobData{
{
Index: "1",
Blob: "00001",
KzgCommitment: "0x83ae1d",
},
},
httpStatus: http.StatusOK,
expectedError: false,
},
{
name: "Internal server error",
blockID: 123,
httpStatus: http.StatusInternalServerError,
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
server := httptest.NewServer(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(tc.httpStatus)
if tc.httpStatus == http.StatusOK {
jsonData, _ := json.Marshal(tc.response)
w.Write(jsonData)
}
}))
defer server.Close()

client := &BeaconClient{
Client: server.Client(),
beaconURL: server.URL,
}

response, err := client.getBlobs(context.Background(), tc.blockID)
if tc.expectedError {
assert.Error(t, err)
} else {
assert.Equal(t, tc.expectedBlobs, response.Data)
}
})
}
}

func TestTimeToSlot(t *testing.T) {
eventTime := time.Now().Unix()
genesisTime := eventTime - 1000

testCases := []struct {
name string
client *BeaconClient
timestamp uint64
expectedSlot uint64
expectedError bool
}{
{
name: "Successful if timestamp is after genesis time",
client: &BeaconClient{
genesisTime: uint64(genesisTime),
secondsPerSlot: 12,
},
timestamp: uint64(eventTime),
expectedSlot: 1000 / 12,
expectedError: false,
},
{
name: "Fails if timestamp is before genesis time",
client: &BeaconClient{
genesisTime: uint64(genesisTime),
secondsPerSlot: 12,
},
timestamp: uint64(genesisTime - 500),
expectedSlot: 0,
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
slot, err := tc.client.timeToSlot(tc.timestamp)

if tc.expectedError {
assert.Error(t, err)
} else {
assert.Equal(t, tc.expectedSlot, slot)
}
})
}
}
3 changes: 0 additions & 3 deletions packages/blobstorage/indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,7 @@ func (i *Indexer) setInitialIndexingBlock(
ctx context.Context,
) error {
// get most recently processed block height from the DB
// latest, err := i.blobHashRepo.FindLatestBlockID()
latest, err := i.repositories.BlockMetaRepo.FindLatestBlockID()
// latest, err := i.blockMetaRepo.FindLatestBlockID()
if err != nil {
return err
}
Expand Down Expand Up @@ -271,7 +269,6 @@ func calculateBlobHash(commitmentStr string) common.Hash {
}

func (i *Indexer) checkReorg(ctx context.Context, event *taikol1.TaikoL1BlockProposed) error {
// n, err := i.blockMetaRepo.FindLatestBlockID()
n, err := i.repositories.BlockMetaRepo.FindLatestBlockID()
if err != nil {
return err
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- +goose Up
ALTER TABLE blocks_meta DROP PRIMARY KEY;
ALTER TABLE blocks_meta ADD COLUMN id INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;

-- +goose Down
ALTER TABLE blocks_meta DROP COLUMN id;
ALTER TABLE blocks_meta ADD PRIMARY KEY (block_id);
26 changes: 26 additions & 0 deletions packages/blobstorage/pkg/mocks/blob_hash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package mocks

import (
"github.com/stretchr/testify/mock"
"github.com/taikoxyz/taiko-mono/packages/blobstorage"
)

type MockBlobHashRepo struct {
mock.Mock
}

func (m *MockBlobHashRepo) FirstByBlobHash(blobHash string) (*blobstorage.BlobHash, error) {
args := m.Called(blobHash)
if item, ok := args.Get(0).(*blobstorage.BlobHash); ok {
return item, args.Error(1)
}
return nil, args.Error(1)
}

func (m *MockBlobHashRepo) Save(opts blobstorage.SaveBlobHashOpts) error {
return m.Called(opts).Error(0)
}

func (m *MockBlobHashRepo) DeleteAllAfterBlockID(blockID uint64) error {
return m.Called(blockID).Error(0)
}
Loading
Loading