mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-24 08:49:29 +00:00
add engine_getBlobsV4
This commit is contained in:
parent
ff731ce79c
commit
6e00052cf5
3 changed files with 144 additions and 1 deletions
|
|
@ -157,6 +157,11 @@ type BlobAndProofV2 struct {
|
|||
CellProofs []hexutil.Bytes `json:"proofs"` // proofs MUST contain exactly CELLS_PER_EXT_BLOB cell proofs.
|
||||
}
|
||||
|
||||
type BlobCellsAndProofsV1 struct {
|
||||
BlobCells []hexutil.Bytes `json:"blob_cells"`
|
||||
Proofs []hexutil.Bytes `json:"proofs"`
|
||||
}
|
||||
|
||||
// JSON type overrides for ExecutionPayloadEnvelope.
|
||||
type executionPayloadEnvelopeMarshaling struct {
|
||||
BlockValue *hexutil.Big
|
||||
|
|
|
|||
|
|
@ -1750,7 +1750,85 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash, version byte) ([]*kzg4844.Blo
|
|||
return blobs, commitments, proofs, nil
|
||||
}
|
||||
|
||||
// AvailableBlobs returns the number of blobs that are available in the subpool.
|
||||
// GetBlobCells returns cells for the given versioned blob hashes,
|
||||
// filtered by the requested cell indices(mask).
|
||||
// Each entry in the result corresponds to one vhash. Nil entries mean the blob
|
||||
// was not available.
|
||||
func (p *BlobPool) GetBlobCells(vhashes []common.Hash, mask types.CustodyBitmap) ([][]*kzg4844.Cell, [][]*kzg4844.Proof, error) {
|
||||
var (
|
||||
cells = make([][]*kzg4844.Cell, len(vhashes))
|
||||
proofs = make([][]*kzg4844.Proof, len(vhashes))
|
||||
vindex = make(map[common.Hash][]int) // Indices of versioned hashes in the request
|
||||
filled = make(map[common.Hash]struct{})
|
||||
)
|
||||
for i, h := range vhashes {
|
||||
vindex[h] = append(vindex[h], i)
|
||||
}
|
||||
requestedIndices := mask.Indices()
|
||||
|
||||
for _, vhash := range vhashes {
|
||||
if _, ok := filled[vhash]; ok {
|
||||
continue
|
||||
}
|
||||
p.lock.RLock()
|
||||
txID, exists := p.lookup.storeidOfBlob(vhash)
|
||||
p.lock.RUnlock()
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
data, err := p.store.Get(txID)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var pooledTx pooledBlobTx
|
||||
if err := rlp.DecodeBytes(data, &pooledTx); err != nil {
|
||||
continue
|
||||
}
|
||||
sidecar := pooledTx.Sidecar
|
||||
if sidecar == nil {
|
||||
continue
|
||||
}
|
||||
tx := pooledTx.Transaction
|
||||
cellsPerBlob := sidecar.Custody.OneCount()
|
||||
storedIndices := sidecar.Custody.Indices()
|
||||
|
||||
for blobIdx, hash := range tx.BlobHashes() {
|
||||
indices, ok := vindex[hash]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
filled[hash] = struct{}{}
|
||||
|
||||
blobCells := make([]*kzg4844.Cell, len(requestedIndices))
|
||||
blobProofs := make([]*kzg4844.Proof, len(requestedIndices))
|
||||
|
||||
for i, cellIdx := range requestedIndices {
|
||||
pos := -1
|
||||
for k, storedIdx := range storedIndices {
|
||||
if storedIdx == cellIdx {
|
||||
pos = k
|
||||
break
|
||||
}
|
||||
}
|
||||
if pos >= 0 {
|
||||
cell := sidecar.Cells[blobIdx*cellsPerBlob+pos]
|
||||
blobCells[i] = &cell
|
||||
proofIdx := blobIdx*kzg4844.CellProofsPerBlob + int(cellIdx)
|
||||
if proofIdx < len(sidecar.Proofs) {
|
||||
proof := sidecar.Proofs[proofIdx]
|
||||
blobProofs[i] = &proof
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, idx := range indices {
|
||||
cells[idx] = blobCells
|
||||
proofs[idx] = blobProofs
|
||||
}
|
||||
}
|
||||
}
|
||||
return cells, proofs, nil
|
||||
}
|
||||
|
||||
func (p *BlobPool) AvailableBlobs(vhashes []common.Hash) int {
|
||||
available := 0
|
||||
for _, vhash := range vhashes {
|
||||
|
|
|
|||
|
|
@ -660,6 +660,66 @@ func (api *ConsensusAPI) getBlobs(hashes []common.Hash, v2 bool) ([]*engine.Blob
|
|||
return res, nil
|
||||
}
|
||||
|
||||
// GetBlobsV4 returns cell-level blob data from the transaction pool.
|
||||
// V4 returns only the requested cells as specified by the indices_bitarray.
|
||||
func (api *ConsensusAPI) GetBlobsV4(hashes []common.Hash, indicesBitarray hexutil.Bytes) ([]*engine.BlobCellsAndProofsV1, error) {
|
||||
head := api.eth.BlockChain().CurrentHeader()
|
||||
// Sparse blobpool is not necessarily coupled with the Amsterdam fork and
|
||||
// can technically be supported after the Osaka fork
|
||||
// (where cell proofs are introduced).
|
||||
if api.config().LatestFork(head.Time) < forks.Osaka {
|
||||
return nil, nil
|
||||
}
|
||||
if len(hashes) > 128 {
|
||||
return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes)))
|
||||
}
|
||||
if len(indicesBitarray) != 16 {
|
||||
return nil, engine.InvalidParams.With(fmt.Errorf("indices_bitarray must be 16 bytes, got %d", len(indicesBitarray)))
|
||||
}
|
||||
var mask types.CustodyBitmap
|
||||
copy(mask[:], indicesBitarray)
|
||||
cells, proofs, err := api.eth.BlobTxPool().GetBlobCells(hashes, mask)
|
||||
if err != nil {
|
||||
return nil, engine.InvalidParams.With(err)
|
||||
}
|
||||
var (
|
||||
res = make([]*engine.BlobCellsAndProofsV1, len(hashes))
|
||||
hitCount int
|
||||
)
|
||||
getBlobsRequestedCounter.Inc(int64(len(hashes)))
|
||||
for i := range hashes {
|
||||
if cells[i] == nil || proofs[i] == nil {
|
||||
continue
|
||||
}
|
||||
hitCount++
|
||||
blobCells := make([]hexutil.Bytes, len(cells[i]))
|
||||
for j, cell := range cells[i] {
|
||||
if cell != nil {
|
||||
blobCells[j] = cell[:]
|
||||
}
|
||||
}
|
||||
blobProofs := make([]hexutil.Bytes, len(proofs[i]))
|
||||
for j, proof := range proofs[i] {
|
||||
if proof != nil {
|
||||
blobProofs[j] = proof[:]
|
||||
}
|
||||
}
|
||||
res[i] = &engine.BlobCellsAndProofsV1{
|
||||
BlobCells: blobCells,
|
||||
Proofs: blobProofs,
|
||||
}
|
||||
}
|
||||
getBlobsAvailableCounter.Inc(int64(hitCount))
|
||||
if hitCount == len(hashes) {
|
||||
getBlobsRequestCompleteHit.Inc(1)
|
||||
} else if hitCount > 0 {
|
||||
getBlobsRequestPartialHit.Inc(1)
|
||||
} else {
|
||||
getBlobsRequestMiss.Inc(1)
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Helper for NewPayload* methods.
|
||||
var invalidStatus = engine.PayloadStatusV1{Status: engine.INVALID}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue