Skip to content

Commit

Permalink
feat: support bsc (#6)
Browse files Browse the repository at this point in the history
* enhancement and grpc server

* feat: support BSC

* feat: bump go to 1.22

* fix pipeline

* clean code

* adapt BSC RPC and add blob extra field
grant allowance
  • Loading branch information
alexgao001 authored Jun 24, 2024
1 parent ec7329d commit 312c24a
Show file tree
Hide file tree
Showing 52 changed files with 3,462 additions and 340 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
build-test:
strategy:
matrix:
go-version: [1.20.x]
go-version: [1.22.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gosec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
name: gosec
strategy:
matrix:
go-version: [1.20.x]
go-version: [1.22.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
name: golangci-lint
strategy:
matrix:
go-version: [1.20.x]
go-version: [1.22.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
env:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Once the bundle is downloaded and extracted, all original blob files can be foun

### Requirement

Go version above 1.20
Go version above 1.22

### Create a bucket on Greenfield

Expand Down
94 changes: 94 additions & 0 deletions client/blob_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package client

import (
"context"
"encoding/hex"
"fmt"

"github.com/ethereum/go-ethereum/common/hexutil"

"github.com/bnb-chain/blob-hub/models"
blobproto "github.com/bnb-chain/blob-hub/proto"
"github.com/bnb-chain/blob-hub/service"
"github.com/bnb-chain/blob-hub/types"
"github.com/bnb-chain/blob-hub/util"
)

type BlobServer struct {
blobproto.UnimplementedBlobServiceServer
service.Blob
}

func (s *BlobServer) GetBlobSidecars(ctx context.Context, req *blobproto.GetBlobSidecarsRequest) (*blobproto.GetBlobSidecarsResponse, error) {
if req == nil {
return nil, fmt.Errorf("invalid request")
}
blockID := req.GetBlockId()
indices := req.GetIndices()

var root []byte
switch blockID {
case "genesis", "finalized":
return nil, fmt.Errorf("block identifier not supported, only <slot> and <block root>")
default:
var (
err error
sidecars []*models.Sidecar
)

indicesInx := make([]int64, 0)
for _, idx := range indices {
i, err := util.StringToInt64(idx)
if err != nil {
return nil, err
}
indicesInx = append(indicesInx, i)
}
root, err = hexutil.Decode(blockID)
if err == nil {
if len(root) != types.RootLength {
return nil, fmt.Errorf("invalid block root of length %d", len(root))
}
sidecars, err = service.BlobSvc.GetBlobSidecarsByRoot(hex.EncodeToString(root), indicesInx)
if err != nil {
return nil, err
}
} else {
blockNumOrSlot, err := util.StringToUint64(blockID)
if err != nil {
return nil, err
}
sidecars, err = service.BlobSvc.GetBlobSidecarsByBlockNumOrSlot(blockNumOrSlot, indicesInx)
if err != nil {
return nil, err
}
}
data := make([]*blobproto.SideCar, 0)
for _, sc := range sidecars {
data = append(
data,
&blobproto.SideCar{
Blob: sc.Blob,
Index: sc.Index,
KzgCommitment: sc.KzgCommitment,
KzgCommitmentInclusionProof: sc.KzgCommitmentInclusionProof,
KzgProof: sc.KzgProof,
SignedBlockHeader: &blobproto.SignedBeaconBlockHeader{
Message: &blobproto.BeaconBlockHeader{
BodyRoot: sc.SignedBlockHeader.Message.BodyRoot,
ParentRoot: sc.SignedBlockHeader.Message.ParentRoot,
StateRoot: sc.SignedBlockHeader.Message.StateRoot,
Slot: sc.SignedBlockHeader.Message.Slot,
ProposerIndex: sc.SignedBlockHeader.Message.ProposerIndex,
},
Signature: sc.SignedBlockHeader.Signature,
},
},
)
}
return &blobproto.GetBlobSidecarsResponse{
Data: data,
}, nil
}

}
47 changes: 32 additions & 15 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"log"
"os"
"strings"
"time"

"gorm.io/driver/mysql"
Expand All @@ -15,13 +16,19 @@ import (
syncerdb "github.com/bnb-chain/blob-hub/db"
)

const (
ETH = "ETH"
BSC = "BSC"
)

type SyncerConfig struct {
BucketName string `json:"bucket_name"` // BucketName is the identifier of bucket on Greenfield that store blob
StartSlot uint64 `json:"start_slot"` // StartSlot is used to init the syncer which slot of beacon chain to synced from, only need to provide once.
CreateBundleSlotInterval uint64 `json:"create_bundle_slot_interval"` // CreateBundleSlotInterval defines the number of slot that syncer would assemble blobs and upload to bundle service
BundleServiceEndpoints []string `json:"bundle_service_endpoints"` // BundleServiceEndpoints is a list of bundle service address
BeaconRPCAddrs []string `json:"beacon_rpc_addrs"` // BeaconRPCAddrs is a list of beacon chain RPC address
ETHRPCAddrs []string `json:"eth_rpc_addrs"`
Chain string `json:"chain"` // support ETH and BSC
BucketName string `json:"bucket_name"` // BucketName is the identifier of bucket on Greenfield that store blob
StartSlotOrBlock uint64 `json:"start_slot_or_block"` // StartSlotOrBlock is used to init the syncer which slot of beacon chain to synced from, only need to provide once.
CreateBundleSlotOrBlockInterval uint64 `json:"create_bundle_slot_or_block_interval"` // CreateBundleSlotOrBlockInterval defines the number of slot that syncer would assemble blobs and upload to bundle service
BundleServiceEndpoints []string `json:"bundle_service_endpoints"` // BundleServiceEndpoints is a list of bundle service address
BeaconRPCAddrs []string `json:"beacon_rpc_addrs"` // BeaconRPCAddrs is a list of beacon chain RPC address
RPCAddrs []string `json:"rpc_addrs"` // RPCAddrs ETH or BSC RPC addr
TempDir string `json:"temp_dir"` // TempDir is used to store blobs and created bundle
PrivateKey string `json:"private_key"` // PrivateKey is the key of bucket owner, request to bundle service will be signed by it as well.
BundleNotSealedReuploadThreshold int64 `json:"bundle_not_sealed_reupload_threshold"` // BundleNotSealedReuploadThreshold for re-uploading a bundle if it cant be sealed within the time threshold.
Expand All @@ -31,19 +38,22 @@ type SyncerConfig struct {
}

func (s *SyncerConfig) Validate() {
if !strings.EqualFold(s.Chain, ETH) && !strings.EqualFold(s.Chain, BSC) {
panic("chain not support")
}
if len(s.BucketName) == 0 {
panic("the Greenfield bucket name is not is not provided")
}
if s.StartSlot == 0 {
if s.StartSlotOrBlock == 0 {
panic("the start slot to sync slot is not provided")
}
if len(s.BundleServiceEndpoints) == 0 {
panic("BundleService endpoints should not be empty")
}
if len(s.BeaconRPCAddrs) == 0 {
if s.Chain == ETH && len(s.BeaconRPCAddrs) == 0 {
panic("beacon rpc address should not be empty")
}
if len(s.ETHRPCAddrs) == 0 {
if len(s.RPCAddrs) == 0 {
panic("eth rpc address should not be empty")
}
if len(s.TempDir) == 0 {
Expand All @@ -52,21 +62,24 @@ func (s *SyncerConfig) Validate() {
if len(s.PrivateKey) == 0 {
panic("private key is not provided")
}
if s.CreateBundleSlotInterval > 30 {
panic("create_bundle_slot_interval is supposed less than 20")
if s.Chain == BSC && s.CreateBundleSlotOrBlockInterval > 200 {
panic("create_bundle_slot_interval is supposed to be less than 100")
}
if s.Chain == ETH && s.CreateBundleSlotOrBlockInterval > 30 {
panic("create_bundle_slot_interval is supposed to be less than 30")
}
if s.BundleNotSealedReuploadThreshold <= 60 {
panic("Bundle_not_sealed_reupload_threshold is supposed larger than 60")
panic("Bundle_not_sealed_reupload_threshold is supposed larger than 60 (s)")
}

s.DBConfig.Validate()
}

func (s *SyncerConfig) GetCreateBundleSlotInterval() uint64 {
if s.CreateBundleSlotInterval == 0 {
func (s *SyncerConfig) GetCreateBundleInterval() uint64 {
if s.CreateBundleSlotOrBlockInterval == 0 {
return DefaultCreateBundleSlotInterval
}
return s.CreateBundleSlotInterval
return s.CreateBundleSlotOrBlockInterval
}

func (s *SyncerConfig) GetReUploadBundleThresh() int64 {
Expand All @@ -77,13 +90,17 @@ func (s *SyncerConfig) GetReUploadBundleThresh() int64 {
}

type ServerConfig struct {
Chain string `json:"chain"`
BucketName string `json:"bucket_name"`
BundleServiceEndpoints []string `json:"bundle_service_endpoints"` // BundleServiceEndpoints is a list of bundle service address
CacheConfig CacheConfig `json:"cache_config"`
DBConfig DBConfig `json:"db_config"`
}

func (s *ServerConfig) Validate() {
if !strings.EqualFold(s.Chain, ETH) && !strings.EqualFold(s.Chain, BSC) {
panic("chain not support")
}
if len(s.BucketName) == 0 {
panic("the Greenfield bucket name is not is not provided")
}
Expand Down
2 changes: 1 addition & 1 deletion config/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const (
EnvVarDBUserPass = "DB_PASSWORD"
EnvVarPrivateKey = "PRIVATE_KEY"

DefaultCreateBundleSlotInterval = 20
DefaultCreateBundleSlotInterval = 30

DefaultReUploadBundleThreshold = 3600 // in second

Expand Down
1 change: 1 addition & 0 deletions db/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Blob struct {
VersionedHash string `gorm:"NOT NULL"`
Slot uint64 `gorm:"NOT NULL;index:idx_blob_slot_index"`
Idx int `gorm:"NOT NULL;index:idx_blob_slot_idx"`
TxIndex int
KzgCommitment string `gorm:"NOT NULL"`
KzgProof string `gorm:"NOT NULL"`
CommitmentInclusionProof string `gorm:"NOT NULL"`
Expand Down
17 changes: 13 additions & 4 deletions db/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,35 @@ func (d *BlobSvcDB) UpdateBlocksStatus(startSlot, endSlot uint64, status Status)
}

type BlobDB interface {
GetBlobBySlot(slot uint64) ([]*Blob, error)
GetBlobBySlotAndIndices(slot uint64, indices []int64) ([]*Blob, error)
GetBlobByBlockID(slot uint64) ([]*Blob, error)
GetBlobByBlockIDAndIndices(slot uint64, indices []int64) ([]*Blob, error)
GetBlobBetweenBlocks(startSlot, endSlot uint64) ([]*Blob, error)
}

func (d *BlobSvcDB) GetBlobBySlot(slot uint64) ([]*Blob, error) {
func (d *BlobSvcDB) GetBlobByBlockID(slot uint64) ([]*Blob, error) {
blobs := make([]*Blob, 0)
if err := d.db.Where("slot = ?", slot).Order("idx asc").Find(&blobs).Error; err != nil {
return blobs, err
}
return blobs, nil
}

func (d *BlobSvcDB) GetBlobBySlotAndIndices(slot uint64, indices []int64) ([]*Blob, error) {
func (d *BlobSvcDB) GetBlobByBlockIDAndIndices(slot uint64, indices []int64) ([]*Blob, error) {
blobs := make([]*Blob, 0)
if err := d.db.Where("slot = ? and idx in (?)", slot, indices).Order("idx asc").Find(&blobs).Error; err != nil {
return blobs, err
}
return blobs, nil
}

func (d *BlobSvcDB) GetBlobBetweenBlocks(startSlot, endSlot uint64) ([]*Blob, error) {
blobs := make([]*Blob, 0)
if err := d.db.Where("slot >= ? and slot <= ?", startSlot, endSlot).Order("idx asc").Find(&blobs).Error; err != nil {
return blobs, err
}
return blobs, nil
}

type BundleDB interface {
GetBundle(name string) (*Bundle, error)
GetLatestFinalizingBundle() (*Bundle, error)
Expand Down
Loading

0 comments on commit 312c24a

Please sign in to comment.