|
8 | 8 | {.push raises: [].} |
9 | 9 |
|
10 | 10 | import |
11 | | - std/[tables], |
| 11 | + std/[tables, sequtils], |
12 | 12 | chronicles, chronos, metrics, |
13 | 13 | taskpools, |
| 14 | + kzg4844/kzg, |
| 15 | + ssz_serialization/types, |
| 16 | + ../el/el_manager, |
14 | 17 | ../spec/[helpers, forks, peerdas_helpers], |
15 | 18 | ../consensus_object_pools/[ |
16 | 19 | blob_quarantine, block_clearance, block_quarantine, blockchain_dag, |
@@ -349,15 +352,80 @@ proc processBlobSidecar*( |
349 | 352 |
|
350 | 353 | v |
351 | 354 |
|
| 355 | +proc validateDataColumnSidecarFromEL*( |
| 356 | + self: ref Eth2Processor, |
| 357 | + block_root: Eth2Digest): |
| 358 | + Future[ValidationRes] |
| 359 | + {.async: (raises: [CancelledError]).} = |
| 360 | + let elManager = self.blockProcessor[].consensusManager.elManager |
| 361 | + if (let o = self.quarantine[].popColumnless(block_root); o.isSome): |
| 362 | + let columnless = o.unsafeGet() |
| 363 | + withBlck(columnless): |
| 364 | + when consensusFork >= ConsensusFork.Fulu: |
| 365 | + let |
| 366 | + start_time = Moment.now() |
| 367 | + let blobsFromElOpt = |
| 368 | + await elManager.sendGetBlobsV2(forkyBlck) |
| 369 | + if blobsFromElOpt.isSome(): |
| 370 | + let blobsEl = blobsFromElOpt.get() |
| 371 | + |
| 372 | + # check lengths of array[BlobAndProofV2 with blobs |
| 373 | + # kzg commitments of the signed block |
| 374 | + if blobsEl.len == forkyBlck.message.body.blob_kzg_commitments.len: |
| 375 | + |
| 376 | + # we have received all columns from the EL |
| 377 | + # hence we can safely remove the columnless block from quarantine |
| 378 | + var flat_proof: seq[kzg.KzgProof] = @[] |
| 379 | + for item in blobsEl: |
| 380 | + for proof in item.proofs: |
| 381 | + flat_proof.add(kzg.KzgProof(bytes: proof.data)) |
| 382 | + |
| 383 | + let |
| 384 | + recovered_columns = |
| 385 | + assemble_data_column_sidecars( |
| 386 | + forkyBlck, |
| 387 | + blobsEl.mapIt(kzg.KzgBlob(bytes: it.blob.data)), |
| 388 | + flat_proof) |
| 389 | + |
| 390 | + # Pop out the column sidecars as we have all columns from the EL |
| 391 | + discard self.dataColumnQuarantine[].popSidecars(block_root, |
| 392 | + forkyBlck) |
| 393 | + |
| 394 | + let end_time = Moment.now() |
| 395 | + debug "Time taken to get 100% response from EL and bypass blob gossip validation", |
| 396 | + time_taken = end_time - start_time |
| 397 | + debug "Pulled blobs from EL, bypassing blob gossip validation", |
| 398 | + blobs_from_el = blobsEl.len |
| 399 | + self.blockProcessor[].enqueueBlock( |
| 400 | + MsgSource.gossip, columnless, |
| 401 | + Opt.none(BlobSidecars), |
| 402 | + Opt.some(recovered_columns.mapIt(newClone it))) |
| 403 | + return ok() |
| 404 | + |
| 405 | + else: |
| 406 | + discard self.quarantine[].addColumnless( |
| 407 | + self.dag.finalizedHead.slot, forkyBlck) |
| 408 | + else: |
| 409 | + raiseAssert "Could not have been added as columnless" |
| 410 | + else: |
| 411 | + return errIgnore ("Could not pull blobs and proofs from EL") |
| 412 | + |
352 | 413 | proc processDataColumnSidecar*( |
353 | | - self: var Eth2Processor, src: MsgSource, |
354 | | - dataColumnSidecar: DataColumnSidecar, subnet_id: uint64): ValidationRes = |
| 414 | + self: ref Eth2Processor, src: MsgSource, |
| 415 | + dataColumnSidecar: DataColumnSidecar, subnet_id: uint64): |
| 416 | + Future[ValidationRes] {.async: (raises: [CancelledError]).} = |
355 | 417 | template block_header: untyped = dataColumnSidecar.signed_block_header.message |
| 418 | + let block_root = hash_tree_root(block_header) |
| 419 | + |
| 420 | + let vEL = |
| 421 | + await self.validateDataColumnSidecarFromEL(block_root) |
| 422 | + |
| 423 | + if vEL.isOk(): |
| 424 | + return vEL |
356 | 425 |
|
357 | 426 | let |
358 | 427 | wallTime = self.getCurrentBeaconTime() |
359 | 428 | (_, wallSlot) = wallTime.toSlot() |
360 | | - block_root = hash_tree_root(block_header) |
361 | 429 |
|
362 | 430 | logScope: |
363 | 431 | dcs = shortLog(dataColumnSidecar) |
@@ -387,17 +455,10 @@ proc processDataColumnSidecar*( |
387 | 455 | let cres = |
388 | 456 | self.dataColumnQuarantine[].popSidecars(block_root, forkyBlck) |
389 | 457 | if cres.isSome(): |
390 | | - if cres.get().lenu64 > (self.dag.cfg.NUMBER_OF_COLUMNS div 2): |
391 | | - # We have enough data columns to reconstruct the rest |
392 | | - let |
393 | | - recovered_cps = recover_cells_and_proofs(cres.get()) |
394 | | - reconstructed_columns = |
395 | | - reconstruct_data_column_sidecars(forkyBlck, recovered_cps.get) |
396 | | - |
397 | | - self.blockProcessor[].enqueueBlock( |
398 | | - MsgSource.gossip, columnless, |
399 | | - Opt.none(BlobSidecars), |
400 | | - Opt.some(reconstructed_columns)) |
| 458 | + self.blockProcessor[].enqueueBlock( |
| 459 | + MsgSource.gossip, columnless, |
| 460 | + Opt.none(BlobSidecars), |
| 461 | + cres) |
401 | 462 | else: |
402 | 463 | discard self.quarantine[].addColumnless( |
403 | 464 | self.dag.finalizedHead.slot, forkyBlck) |
|
0 commit comments