-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(blobstorage): blockId determination by timestamp (#16614)
Co-authored-by: jeff <[email protected]> Co-authored-by: David <[email protected]>
- Loading branch information
1 parent
5f75dd8
commit eba19c7
Showing
4 changed files
with
161 additions
and
33 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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,135 @@ | ||
package indexer | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
var ( | ||
blobURL = "eth/v1/beacon/blob_sidecars" | ||
genesisURL = "eth/v1/beacon/genesis" | ||
configURL = "eth/v1/config/spec" | ||
) | ||
|
||
type GetSpecResponse struct { | ||
Data map[string]string `json:"data"` | ||
} | ||
|
||
type GenesisResponse struct { | ||
Data struct { | ||
GenesisTime string `json:"genesis_time"` | ||
} `json:"data"` | ||
} | ||
|
||
type BeaconClient struct { | ||
*http.Client | ||
beaconURL string | ||
genesisTime uint64 | ||
secondsPerSlot uint64 | ||
} | ||
|
||
type BlobsResponse struct { | ||
Data []struct { | ||
Index string `json:"index"` | ||
Blob string `json:"blob"` | ||
KzgCommitment string `json:"kzg_commitment"` | ||
KzgCommitmentHex []byte `json:"-"` | ||
} `json:"data"` | ||
} | ||
|
||
func NewBeaconClient(cfg *Config, timeout time.Duration) (*BeaconClient, error) { | ||
httpClient := &http.Client{Timeout: timeout} | ||
|
||
// Get the genesis time. | ||
url := fmt.Sprintf("%s/%s", cfg.BeaconURL, genesisURL) | ||
genesisTime, err := getGenesisTime(url, httpClient) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get genesis time: %v", err) | ||
} | ||
|
||
url = fmt.Sprintf("%s/%s", cfg.BeaconURL, configURL) | ||
// Get the seconds per slot. | ||
secondsPerSlot, err := getConfigValue(url, "SECONDS_PER_SLOT", httpClient) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to get SECONDS_PER_SLOT: %v", err) | ||
} | ||
|
||
secondsPerSlotUint64, err := strconv.ParseUint(secondsPerSlot, 10, 64) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &BeaconClient{ | ||
beaconURL: cfg.BeaconURL, | ||
genesisTime: genesisTime, | ||
secondsPerSlot: secondsPerSlotUint64, | ||
}, nil | ||
} | ||
|
||
func getGenesisTime(endpoint string, client *http.Client) (uint64, error) { | ||
res, err := client.Get(endpoint) | ||
if err != nil { | ||
return 0, err | ||
} | ||
defer res.Body.Close() | ||
|
||
var genesisDetail GenesisResponse | ||
if err := json.NewDecoder(res.Body).Decode(&genesisDetail); err != nil { | ||
return 0, err | ||
} | ||
|
||
return strconv.ParseUint(genesisDetail.Data.GenesisTime, 10, 64) | ||
} | ||
|
||
func getConfigValue(endpoint, key string, client *http.Client) (string, error) { | ||
res, err := client.Get(endpoint) | ||
if err != nil { | ||
return "", err | ||
} | ||
defer res.Body.Close() | ||
|
||
var spec GetSpecResponse | ||
if err := json.NewDecoder(res.Body).Decode(&spec); err != nil { | ||
return "", err | ||
} | ||
|
||
value, ok := spec.Data[key] | ||
if !ok { | ||
return "", fmt.Errorf("key %s not found in config spec", key) | ||
} | ||
|
||
return value, nil | ||
} | ||
|
||
func (c *BeaconClient) getBlobs(ctx context.Context, blockID uint64) (*BlobsResponse, error) { | ||
url := fmt.Sprintf("%s/%s/%v", c.beaconURL, blobURL, blockID) | ||
response, err := http.Get(url) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer response.Body.Close() | ||
|
||
body, err := io.ReadAll(response.Body) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var responseData BlobsResponse | ||
if err := json.Unmarshal(body, &responseData); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &responseData, nil | ||
} | ||
|
||
func (c *BeaconClient) timeToSlot(timestamp uint64) (uint64, error) { | ||
if timestamp < c.genesisTime { | ||
return 0, fmt.Errorf("provided timestamp (%v) precedes genesis time (%v)", timestamp, c.genesisTime) | ||
} | ||
return (timestamp - c.genesisTime) / c.secondsPerSlot, nil | ||
} |
This file contains 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
This file contains 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