mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
9 Commits
eas-bug
...
data-colum
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9e093d8a3 | ||
|
|
c990d1d90c | ||
|
|
a77a3a1740 | ||
|
|
fa616d4afd | ||
|
|
9d0d0f524d | ||
|
|
f71b821f88 | ||
|
|
f15cef7266 | ||
|
|
90e49d5a7e | ||
|
|
77d84f693e |
@@ -74,7 +74,7 @@ func FetchDataColumnSidecars(
|
||||
// set as we retrieve them.
|
||||
incompleteRoots := make(map[[fieldparams.RootLength]byte]bool, blockCount)
|
||||
slotsWithCommitments := make(map[primitives.Slot]bool, blockCount)
|
||||
slotByRoot := make(map[[fieldparams.RootLength]byte]primitives.Slot, blockCount)
|
||||
roBlockByRoot := make(map[[fieldparams.RootLength]byte]blocks.ROBlock, blockCount)
|
||||
storedIndicesByRoot := make(map[[fieldparams.RootLength]byte]map[uint64]bool, blockCount)
|
||||
|
||||
for _, roBlock := range roBlocks {
|
||||
@@ -93,7 +93,7 @@ func FetchDataColumnSidecars(
|
||||
slot := block.Slot()
|
||||
|
||||
incompleteRoots[root] = true
|
||||
slotByRoot[root] = slot
|
||||
roBlockByRoot[root] = roBlock
|
||||
slotsWithCommitments[slot] = true
|
||||
|
||||
storedIndices := params.Storage.Summary(root).Stored()
|
||||
@@ -118,7 +118,7 @@ func FetchDataColumnSidecars(
|
||||
}
|
||||
|
||||
// Request direct sidecars from peers.
|
||||
directSidecarsByRoot, err := requestDirectSidecarsFromPeers(params, slotByRoot, requestedIndices, slotsWithCommitments, storedIndicesByRoot, incompleteRoots)
|
||||
directSidecarsByRoot, err := requestDirectSidecarsFromPeers(params, roBlockByRoot, requestedIndices, slotsWithCommitments, storedIndicesByRoot, incompleteRoots)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "request direct sidecars from peers")
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func FetchDataColumnSidecars(
|
||||
}
|
||||
|
||||
// Request all possible indirect sidecars from peers which are neither stored nor in `directSidecarsByRoot`
|
||||
indirectSidecarsByRoot, err := requestIndirectSidecarsFromPeers(params, slotByRoot, slotsWithCommitments, storedIndicesByRoot, directSidecarsByRoot, requestedIndices, incompleteRoots)
|
||||
indirectSidecarsByRoot, err := requestIndirectSidecarsFromPeers(params, roBlockByRoot, slotsWithCommitments, storedIndicesByRoot, directSidecarsByRoot, requestedIndices, incompleteRoots)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "request all sidecars from peers")
|
||||
}
|
||||
@@ -229,7 +229,7 @@ func requestSidecarsFromStorage(
|
||||
// It returns a map from each root to its successfully retrieved sidecars.
|
||||
func requestDirectSidecarsFromPeers(
|
||||
params DataColumnSidecarsParams,
|
||||
slotByRoot map[[fieldparams.RootLength]byte]primitives.Slot,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
requestedIndices map[uint64]bool,
|
||||
slotsWithCommitments map[primitives.Slot]bool,
|
||||
storedIndicesByRoot map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
@@ -266,7 +266,7 @@ func requestDirectSidecarsFromPeers(
|
||||
|
||||
initialMissingCount := computeTotalCount(missingIndicesByRoot)
|
||||
|
||||
indicesByRootByPeer, err := computeIndicesByRootByPeer(params.P2P, slotByRoot, missingIndicesByRoot, connectedPeers)
|
||||
indicesByRootByPeer, err := computeIndicesByRootByPeer(params.P2P, roBlockByRoot, missingIndicesByRoot, connectedPeers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "explore peers")
|
||||
}
|
||||
@@ -285,10 +285,10 @@ func requestDirectSidecarsFromPeers(
|
||||
}
|
||||
|
||||
// Fetch the sidecars from the chosen peers.
|
||||
roDataColumnsByPeer := fetchDataColumnSidecarsFromPeers(params, slotByRoot, slotsWithCommitments, indicesByRootByPeerToQuery)
|
||||
roDataColumnsByPeer := fetchDataColumnSidecarsFromPeers(params, roBlockByRoot, slotsWithCommitments, indicesByRootByPeerToQuery)
|
||||
|
||||
// Verify the received data column sidecars.
|
||||
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(params.P2P, params.NewVerifier, roDataColumnsByPeer)
|
||||
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(params.P2P, params.NewVerifier, roBlockByRoot, roDataColumnsByPeer)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "verify data columns sidecars by peer")
|
||||
}
|
||||
@@ -300,7 +300,7 @@ func requestDirectSidecarsFromPeers(
|
||||
}
|
||||
|
||||
// Compute indices by root by peers with the updated missing indices and connected peers.
|
||||
indicesByRootByPeer, err = computeIndicesByRootByPeer(params.P2P, slotByRoot, missingIndicesByRoot, connectedPeers)
|
||||
indicesByRootByPeer, err = computeIndicesByRootByPeer(params.P2P, roBlockByRoot, missingIndicesByRoot, connectedPeers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "explore peers")
|
||||
}
|
||||
@@ -323,7 +323,7 @@ func requestDirectSidecarsFromPeers(
|
||||
// - all peers are exhausted.
|
||||
func requestIndirectSidecarsFromPeers(
|
||||
p DataColumnSidecarsParams,
|
||||
slotByRoot map[[fieldparams.RootLength]byte]primitives.Slot,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
slotsWithCommitments map[primitives.Slot]bool,
|
||||
storedIndicesByRoot map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
alreadyAvailableByRoot map[[fieldparams.RootLength]byte][]blocks.VerifiedRODataColumn,
|
||||
@@ -370,7 +370,7 @@ func requestIndirectSidecarsFromPeers(
|
||||
}
|
||||
|
||||
// Compute which peers have which of the missing indices.
|
||||
indicesByRootByPeer, err := computeIndicesByRootByPeer(p.P2P, slotByRoot, indicesToRetrieveByRoot, connectedPeers)
|
||||
indicesByRootByPeer, err := computeIndicesByRootByPeer(p.P2P, roBlockByRoot, indicesToRetrieveByRoot, connectedPeers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "explore peers")
|
||||
}
|
||||
@@ -395,10 +395,10 @@ func requestIndirectSidecarsFromPeers(
|
||||
}
|
||||
|
||||
// Fetch the sidecars from the chosen peers.
|
||||
roDataColumnsByPeer := fetchDataColumnSidecarsFromPeers(p, slotByRoot, slotsWithCommitments, indicesByRootByPeerToQuery)
|
||||
roDataColumnsByPeer := fetchDataColumnSidecarsFromPeers(p, roBlockByRoot, slotsWithCommitments, indicesByRootByPeerToQuery)
|
||||
|
||||
// Verify the received data column sidecars.
|
||||
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(p.P2P, p.NewVerifier, roDataColumnsByPeer)
|
||||
verifiedRoDataColumnSidecars, err := verifyDataColumnSidecarsByPeer(p.P2P, p.NewVerifier, roBlockByRoot, roDataColumnsByPeer)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "verify data columns sidecars by peer")
|
||||
}
|
||||
@@ -436,7 +436,7 @@ func requestIndirectSidecarsFromPeers(
|
||||
}
|
||||
|
||||
// Compute indices by root by peers with the updated missing indices and connected peers.
|
||||
indicesByRootByPeer, err = computeIndicesByRootByPeer(p.P2P, slotByRoot, indicesToRetrieveByRoot, connectedPeers)
|
||||
indicesByRootByPeer, err = computeIndicesByRootByPeer(p.P2P, roBlockByRoot, indicesToRetrieveByRoot, connectedPeers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "explore peers")
|
||||
}
|
||||
@@ -709,7 +709,7 @@ func updateResults(
|
||||
// fetchDataColumnSidecarsFromPeers retrieves data column sidecars from peers.
|
||||
func fetchDataColumnSidecarsFromPeers(
|
||||
params DataColumnSidecarsParams,
|
||||
slotByRoot map[[fieldparams.RootLength]byte]primitives.Slot,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
slotsWithCommitments map[primitives.Slot]bool,
|
||||
indicesByRootByPeer map[goPeer.ID]map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
) map[goPeer.ID][]blocks.RODataColumn {
|
||||
@@ -736,7 +736,7 @@ func fetchDataColumnSidecarsFromPeers(
|
||||
"totalRequestedCount": requestedCount,
|
||||
})
|
||||
|
||||
roDataColumns, err := sendDataColumnSidecarsRequest(params, slotByRoot, slotsWithCommitments, peerID, indicesByRoot)
|
||||
roDataColumns, err := sendDataColumnSidecarsRequest(params, roBlockByRoot, slotsWithCommitments, peerID, indicesByRoot)
|
||||
if err != nil {
|
||||
log.WithError(err).Debug("Failed to send data column sidecars request")
|
||||
return
|
||||
@@ -755,7 +755,7 @@ func fetchDataColumnSidecarsFromPeers(
|
||||
|
||||
func sendDataColumnSidecarsRequest(
|
||||
params DataColumnSidecarsParams,
|
||||
slotByRoot map[[fieldparams.RootLength]byte]primitives.Slot,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
slotsWithCommitments map[primitives.Slot]bool,
|
||||
peerID goPeer.ID,
|
||||
indicesByRoot map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
@@ -775,7 +775,7 @@ func sendDataColumnSidecarsRequest(
|
||||
})
|
||||
|
||||
// Try to build a by range byRangeRequest first.
|
||||
byRangeRequests, err := buildByRangeRequests(slotByRoot, slotsWithCommitments, indicesByRoot, batchSize)
|
||||
byRangeRequests, err := buildByRangeRequests(roBlockByRoot, slotsWithCommitments, indicesByRoot, batchSize)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "craft by range request")
|
||||
}
|
||||
@@ -854,7 +854,7 @@ func sendDataColumnSidecarsRequest(
|
||||
// (Missing blocks or blocks without commitments do count as contiguous)
|
||||
// If one of this condition is not met, returns nil.
|
||||
func buildByRangeRequests(
|
||||
slotByRoot map[[fieldparams.RootLength]byte]primitives.Slot,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
slotsWithCommitments map[primitives.Slot]bool,
|
||||
indicesByRoot map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
batchSize uint64,
|
||||
@@ -864,7 +864,7 @@ func buildByRangeRequests(
|
||||
}
|
||||
|
||||
var reference map[uint64]bool
|
||||
slots := make([]primitives.Slot, 0, len(slotByRoot))
|
||||
slots := make([]primitives.Slot, 0, len(roBlockByRoot))
|
||||
for root, indices := range indicesByRoot {
|
||||
if reference == nil {
|
||||
reference = indices
|
||||
@@ -874,12 +874,12 @@ func buildByRangeRequests(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
slot, ok := slotByRoot[root]
|
||||
roBlock, ok := roBlockByRoot[root]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("slot not found for block root %#x", root)
|
||||
}
|
||||
|
||||
slots = append(slots, slot)
|
||||
slots = append(slots, roBlock.Block().Slot())
|
||||
}
|
||||
|
||||
slices.Sort(slots)
|
||||
@@ -944,6 +944,7 @@ func buildByRootRequest(indicesByRoot map[[fieldparams.RootLength]byte]map[uint6
|
||||
func verifyDataColumnSidecarsByPeer(
|
||||
p2p prysmP2P.P2P,
|
||||
newVerifier verification.NewDataColumnsVerifier,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
roDataColumnsByPeer map[goPeer.ID][]blocks.RODataColumn,
|
||||
) ([]blocks.VerifiedRODataColumn, error) {
|
||||
// First optimistically verify all received data columns in a single batch.
|
||||
@@ -957,7 +958,7 @@ func verifyDataColumnSidecarsByPeer(
|
||||
roDataColumnSidecars = append(roDataColumnSidecars, columns...)
|
||||
}
|
||||
|
||||
verifiedRoDataColumnSidecars, err := verifyByRootDataColumnSidecars(newVerifier, roDataColumnSidecars)
|
||||
verifiedRoDataColumnSidecars, err := verifyRPCDataColumnSidecars(newVerifier, roBlockByRoot, roDataColumnSidecars)
|
||||
if err == nil {
|
||||
// This is the happy path where all sidecars are verified.
|
||||
return verifiedRoDataColumnSidecars, nil
|
||||
@@ -967,7 +968,7 @@ func verifyDataColumnSidecarsByPeer(
|
||||
// Reverify peer by peer to identify faulty peer(s), reject all its sidecars, and downscore it.
|
||||
verifiedRoDataColumnSidecars = make([]blocks.VerifiedRODataColumn, 0, count)
|
||||
for peer, columns := range roDataColumnsByPeer {
|
||||
peerVerifiedRoDataColumnSidecars, err := verifyByRootDataColumnSidecars(newVerifier, columns)
|
||||
peerVerifiedRoDataColumnSidecars, err := verifyRPCDataColumnSidecars(newVerifier, roBlockByRoot, columns)
|
||||
if err != nil {
|
||||
// This peer has invalid sidecars.
|
||||
log := log.WithError(err).WithField("peerID", peer)
|
||||
@@ -982,15 +983,23 @@ func verifyDataColumnSidecarsByPeer(
|
||||
return verifiedRoDataColumnSidecars, nil
|
||||
}
|
||||
|
||||
// verifyByRootDataColumnSidecars verifies the provided read-only data columns against the
|
||||
// verifyRPCDataColumnSidecars verifies the provided read-only data columns against the
|
||||
// requirements for data column sidecars received via the by root request.
|
||||
func verifyByRootDataColumnSidecars(newVerifier verification.NewDataColumnsVerifier, roDataColumns []blocks.RODataColumn) ([]blocks.VerifiedRODataColumn, error) {
|
||||
verifier := newVerifier(roDataColumns, verification.ByRootRequestDataColumnSidecarRequirements)
|
||||
func verifyRPCDataColumnSidecars(
|
||||
newVerifier verification.NewDataColumnsVerifier,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
roDataColumns []blocks.RODataColumn,
|
||||
) ([]blocks.VerifiedRODataColumn, error) {
|
||||
verifier := newVerifier(roDataColumns, verification.RPCDataColumnSidecarRequirements)
|
||||
|
||||
if err := verifier.ValidFields(); err != nil {
|
||||
return nil, errors.Wrap(err, "valid fields")
|
||||
}
|
||||
|
||||
if err := verifier.SidecarRootAndSignatureAligned(roBlockByRoot); err != nil {
|
||||
return nil, errors.Wrap(err, "sidecar root and signature aligned")
|
||||
}
|
||||
|
||||
if err := verifier.SidecarInclusionProven(); err != nil {
|
||||
return nil, errors.Wrap(err, "sidecar inclusion proven")
|
||||
}
|
||||
@@ -1008,12 +1017,12 @@ func verifyByRootDataColumnSidecars(newVerifier verification.NewDataColumnsVerif
|
||||
}
|
||||
|
||||
// computeIndicesByRootByPeer returns a peers->root->indices map only for
|
||||
// root and indices given in `indicesByBlockRoot`. It also only selects peers
|
||||
// root and indices given in `indicesByRoot`. It also only selects peers
|
||||
// for a given root only if its head state is higher than the block slot.
|
||||
func computeIndicesByRootByPeer(
|
||||
p2p prysmP2P.P2P,
|
||||
slotByBlockRoot map[[fieldparams.RootLength]byte]primitives.Slot,
|
||||
indicesByBlockRoot map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock,
|
||||
indicesByRoot map[[fieldparams.RootLength]byte]map[uint64]bool,
|
||||
peers map[goPeer.ID]bool,
|
||||
) (map[goPeer.ID]map[[fieldparams.RootLength]byte]map[uint64]bool, error) {
|
||||
slotsPerEpoch := params.BeaconConfig().SlotsPerEpoch
|
||||
@@ -1065,10 +1074,10 @@ func computeIndicesByRootByPeer(
|
||||
|
||||
// For each block root and its indices, find suitable peers
|
||||
indicesByRootByPeer := make(map[goPeer.ID]map[[fieldparams.RootLength]byte]map[uint64]bool)
|
||||
for blockRoot, indices := range indicesByBlockRoot {
|
||||
blockSlot, ok := slotByBlockRoot[blockRoot]
|
||||
for root, indices := range indicesByRoot {
|
||||
roBlock, ok := roBlockByRoot[root]
|
||||
if !ok {
|
||||
return nil, errors.Errorf("slot not found for block root %#x", blockRoot)
|
||||
return nil, errors.Errorf("slot not found for block root %#x", root)
|
||||
}
|
||||
|
||||
for index := range indices {
|
||||
@@ -1079,7 +1088,7 @@ func computeIndicesByRootByPeer(
|
||||
return nil, errors.Errorf("head slot not found for peer %s", peer)
|
||||
}
|
||||
|
||||
if peerHeadSlot < blockSlot {
|
||||
if peerHeadSlot < roBlock.Block().Slot() {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1087,10 +1096,10 @@ func computeIndicesByRootByPeer(
|
||||
if _, exists := indicesByRootByPeer[peer]; !exists {
|
||||
indicesByRootByPeer[peer] = make(map[[fieldparams.RootLength]byte]map[uint64]bool)
|
||||
}
|
||||
if _, exists := indicesByRootByPeer[peer][blockRoot]; !exists {
|
||||
indicesByRootByPeer[peer][blockRoot] = make(map[uint64]bool)
|
||||
if _, exists := indicesByRootByPeer[peer][root]; !exists {
|
||||
indicesByRootByPeer[peer][root] = make(map[uint64]bool)
|
||||
}
|
||||
indicesByRootByPeer[peer][blockRoot][index] = true
|
||||
indicesByRootByPeer[peer][root][index] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,12 +400,12 @@ func TestFetchDataColumnSidecarsFromPeers(t *testing.T) {
|
||||
expectedResponseSidecar, err := blocks.NewRODataColumn(expectedResponseSidecarPb)
|
||||
require.NoError(t, err)
|
||||
|
||||
slotByRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
{1}: 1,
|
||||
{3}: 3,
|
||||
{4}: 4,
|
||||
{7}: 7,
|
||||
}
|
||||
})
|
||||
|
||||
slotsWithCommitments := map[primitives.Slot]bool{
|
||||
1: true,
|
||||
@@ -458,7 +458,7 @@ func TestFetchDataColumnSidecarsFromPeers(t *testing.T) {
|
||||
other.PeerID(): {expectedResponseSidecar},
|
||||
}
|
||||
|
||||
actualResponse := fetchDataColumnSidecarsFromPeers(params, slotByRoot, slotsWithCommitments, indicesByRootByPeer)
|
||||
actualResponse := fetchDataColumnSidecarsFromPeers(params, roBlockByRoot, slotsWithCommitments, indicesByRootByPeer)
|
||||
require.Equal(t, len(expectedResponse), len(actualResponse))
|
||||
|
||||
for peerID := range expectedResponse {
|
||||
@@ -508,12 +508,12 @@ func TestSendDataColumnSidecarsRequest(t *testing.T) {
|
||||
{7}: {1: true, 2: true},
|
||||
}
|
||||
|
||||
slotByRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
{1}: 1,
|
||||
{3}: 3,
|
||||
{4}: 4,
|
||||
{7}: 7,
|
||||
}
|
||||
})
|
||||
|
||||
slotsWithCommitments := map[primitives.Slot]bool{
|
||||
1: true,
|
||||
@@ -553,7 +553,7 @@ func TestSendDataColumnSidecarsRequest(t *testing.T) {
|
||||
RateLimiter: leakybucket.NewCollector(1., 1, time.Second, false /* deleteEmptyBuckets */),
|
||||
}
|
||||
|
||||
actualResponse, err := sendDataColumnSidecarsRequest(params, slotByRoot, slotsWithCommitments, other.PeerID(), indicesByRoot)
|
||||
actualResponse, err := sendDataColumnSidecarsRequest(params, roBlockByRoot, slotsWithCommitments, other.PeerID(), indicesByRoot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, expectedResponse, actualResponse[0])
|
||||
})
|
||||
@@ -565,11 +565,11 @@ func TestSendDataColumnSidecarsRequest(t *testing.T) {
|
||||
{7}: {1: true, 2: true},
|
||||
}
|
||||
|
||||
slotByRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
expectedResponse.BlockRoot(): 1,
|
||||
{4}: 4,
|
||||
{7}: 7,
|
||||
}
|
||||
})
|
||||
|
||||
slotsWithCommitments := map[primitives.Slot]bool{
|
||||
1: true,
|
||||
@@ -620,7 +620,7 @@ func TestSendDataColumnSidecarsRequest(t *testing.T) {
|
||||
RateLimiter: leakybucket.NewCollector(1., 1, time.Second, false /* deleteEmptyBuckets */),
|
||||
}
|
||||
|
||||
actualResponse, err := sendDataColumnSidecarsRequest(params, slotByRoot, slotsWithCommitments, other.PeerID(), indicesByRoot)
|
||||
actualResponse, err := sendDataColumnSidecarsRequest(params, roBlockByRoot, slotsWithCommitments, other.PeerID(), indicesByRoot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, expectedResponse, actualResponse[0])
|
||||
})
|
||||
@@ -652,13 +652,13 @@ func TestBuildByRangeRequests(t *testing.T) {
|
||||
{3}: {2: true, 3: true},
|
||||
}
|
||||
|
||||
slotByRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
{1}: 1,
|
||||
{2}: 2,
|
||||
{3}: 3,
|
||||
}
|
||||
})
|
||||
|
||||
actual, err := buildByRangeRequests(slotByRoot, nil, indicesByRoot, nullBatchSize)
|
||||
actual, err := buildByRangeRequests(roBlockByRoot, nil, indicesByRoot, nullBatchSize)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(actual))
|
||||
})
|
||||
@@ -669,10 +669,10 @@ func TestBuildByRangeRequests(t *testing.T) {
|
||||
{2}: {1: true, 2: true},
|
||||
}
|
||||
|
||||
slotByRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
{1}: 1,
|
||||
{2}: 3,
|
||||
}
|
||||
})
|
||||
|
||||
slotsWithCommitments := map[primitives.Slot]bool{
|
||||
1: true,
|
||||
@@ -680,7 +680,7 @@ func TestBuildByRangeRequests(t *testing.T) {
|
||||
3: true,
|
||||
}
|
||||
|
||||
actual, err := buildByRangeRequests(slotByRoot, slotsWithCommitments, indicesByRoot, nullBatchSize)
|
||||
actual, err := buildByRangeRequests(roBlockByRoot, slotsWithCommitments, indicesByRoot, nullBatchSize)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(actual))
|
||||
})
|
||||
@@ -695,12 +695,12 @@ func TestBuildByRangeRequests(t *testing.T) {
|
||||
{7}: {1: true, 2: true},
|
||||
}
|
||||
|
||||
slotByRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
{1}: 1,
|
||||
{3}: 3,
|
||||
{4}: 4,
|
||||
{7}: 7,
|
||||
}
|
||||
})
|
||||
|
||||
slotsWithCommitments := map[primitives.Slot]bool{
|
||||
1: true,
|
||||
@@ -727,7 +727,7 @@ func TestBuildByRangeRequests(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
actual, err := buildByRangeRequests(slotByRoot, slotsWithCommitments, indicesByRoot, batchSize)
|
||||
actual, err := buildByRangeRequests(roBlockByRoot, slotsWithCommitments, indicesByRoot, batchSize)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, expected, actual)
|
||||
})
|
||||
@@ -792,7 +792,12 @@ func TestVerifyDataColumnSidecarsByPeer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
newDataColumnsVerifier := newDataColumnsVerifierFromInitializer(initializer)
|
||||
actual, err := verifyDataColumnSidecarsByPeer(p2p, newDataColumnsVerifier, roDataColumnsByPeer)
|
||||
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roDataColumnSidecars[0].BlockRoot(): roDataColumnSidecars[0].Slot(),
|
||||
})
|
||||
|
||||
actual, err := verifyDataColumnSidecarsByPeer(p2p, newDataColumnsVerifier, roBlockByRoot, roDataColumnsByPeer)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, stop-start, len(actual))
|
||||
@@ -837,7 +842,12 @@ func TestVerifyDataColumnSidecarsByPeer(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
newDataColumnsVerifier := newDataColumnsVerifierFromInitializer(initializer)
|
||||
actual, err := verifyDataColumnSidecarsByPeer(p2p, newDataColumnsVerifier, roDataColumnsByPeer)
|
||||
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
roDataColumnSidecars[0].BlockRoot(): roDataColumnSidecars[0].Slot(),
|
||||
})
|
||||
|
||||
actual, err := verifyDataColumnSidecarsByPeer(p2p, newDataColumnsVerifier, roBlockByRoot, roDataColumnsByPeer)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, middle-start, len(actual))
|
||||
@@ -881,34 +891,34 @@ func TestComputeIndicesByRootByPeer(t *testing.T) {
|
||||
peerIDs = append(peerIDs, peerID)
|
||||
}
|
||||
|
||||
slotByBlockRoot := map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
[fieldparams.RootLength]byte{1}: 8,
|
||||
[fieldparams.RootLength]byte{2}: 10,
|
||||
[fieldparams.RootLength]byte{3}: 9,
|
||||
[fieldparams.RootLength]byte{4}: 50,
|
||||
}
|
||||
roBlockByRoot := createRoBlockByRoot(t, map[[fieldparams.RootLength]byte]primitives.Slot{
|
||||
{1}: 8,
|
||||
{2}: 10,
|
||||
{3}: 9,
|
||||
{4}: 50,
|
||||
})
|
||||
|
||||
indicesByBlockRoot := map[[fieldparams.RootLength]byte]map[uint64]bool{
|
||||
[fieldparams.RootLength]byte{1}: {3: true, 4: true, 5: true},
|
||||
[fieldparams.RootLength]byte{2}: {1: true, 10: true, 37: true, 80: true},
|
||||
[fieldparams.RootLength]byte{3}: {10: true, 38: true, 39: true, 40: true},
|
||||
[fieldparams.RootLength]byte{4}: {89: true, 108: true, 122: true},
|
||||
{1}: {3: true, 4: true, 5: true},
|
||||
{2}: {1: true, 10: true, 37: true, 80: true},
|
||||
{3}: {10: true, 38: true, 39: true, 40: true},
|
||||
{4}: {89: true, 108: true, 122: true},
|
||||
}
|
||||
|
||||
expected := map[peer.ID]map[[fieldparams.RootLength]byte]map[uint64]bool{
|
||||
peerIDs[0]: {
|
||||
[fieldparams.RootLength]byte{4}: {89: true, 122: true},
|
||||
{4}: {89: true, 122: true},
|
||||
},
|
||||
peerIDs[1]: {
|
||||
[fieldparams.RootLength]byte{2}: {1: true, 37: true},
|
||||
{2}: {1: true, 37: true},
|
||||
},
|
||||
peerIDs[2]: {
|
||||
[fieldparams.RootLength]byte{2}: {37: true},
|
||||
[fieldparams.RootLength]byte{3}: {38: true},
|
||||
{2}: {37: true},
|
||||
{3}: {38: true},
|
||||
},
|
||||
peerIDs[3]: {
|
||||
[fieldparams.RootLength]byte{2}: {10: true},
|
||||
[fieldparams.RootLength]byte{3}: {10: true},
|
||||
{2}: {10: true},
|
||||
{3}: {10: true},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -917,7 +927,7 @@ func TestComputeIndicesByRootByPeer(t *testing.T) {
|
||||
peerIDsMap[id] = true
|
||||
}
|
||||
|
||||
actual, err := computeIndicesByRootByPeer(p2p, slotByBlockRoot, indicesByBlockRoot, peerIDsMap)
|
||||
actual, err := computeIndicesByRootByPeer(p2p, roBlockByRoot, indicesByBlockRoot, peerIDsMap)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(expected), len(actual))
|
||||
|
||||
@@ -1023,3 +1033,20 @@ func TestComputeTotalCount(t *testing.T) {
|
||||
actual := computeTotalCount(input)
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func createRoBlockByRoot(t *testing.T, slotByRoot map[[fieldparams.RootLength]byte]primitives.Slot) map[[fieldparams.RootLength]byte]blocks.ROBlock {
|
||||
roBlockByRoot := make(map[[fieldparams.RootLength]byte]blocks.ROBlock, len(slotByRoot))
|
||||
for root, slot := range slotByRoot {
|
||||
signedBeaconBlockPb := util.NewBeaconBlock()
|
||||
signedBeaconBlockPb.Block.Slot = slot
|
||||
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
||||
require.NoError(t, err)
|
||||
|
||||
roBlock, err := blocks.NewROBlockWithRoot(signedBeaconBlock, root)
|
||||
require.NoError(t, err)
|
||||
|
||||
roBlockByRoot[root] = roBlock
|
||||
}
|
||||
|
||||
return roBlockByRoot
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p"
|
||||
p2ptest "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/testing"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/types"
|
||||
p2pTypes "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/types"
|
||||
p2ptypes "github.com/OffchainLabs/prysm/v6/beacon-chain/p2p/types"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/startup"
|
||||
"github.com/OffchainLabs/prysm/v6/beacon-chain/verification"
|
||||
fieldparams "github.com/OffchainLabs/prysm/v6/config/fieldparams"
|
||||
@@ -80,7 +78,7 @@ func TestSendRequest_SendBeaconBlocksByRangeRequest(t *testing.T) {
|
||||
}
|
||||
_, err := stream.Write([]byte{0x01})
|
||||
assert.NoError(t, err)
|
||||
msg := p2pTypes.ErrorMessage(processorErr.Error())
|
||||
msg := types.ErrorMessage(processorErr.Error())
|
||||
_, err = p2pProvider.Encoding().EncodeWithMaxLength(stream, &msg)
|
||||
assert.NoError(t, err)
|
||||
return
|
||||
@@ -323,7 +321,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
bogusPeer := p2ptest.NewTestP2P(t)
|
||||
p1.Connect(bogusPeer)
|
||||
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{}
|
||||
req := &types.BeaconBlockByRootsReq{}
|
||||
_, err := SendBeaconBlocksByRootRequest(ctx, startup.NewClock(time.Now(), [32]byte{}), p1, bogusPeer.PeerID(), req, nil)
|
||||
assert.ErrorContains(t, "protocols not supported", err)
|
||||
})
|
||||
@@ -334,7 +332,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
assert.NoError(t, stream.Close())
|
||||
}()
|
||||
|
||||
req := new(p2pTypes.BeaconBlockByRootsReq)
|
||||
req := new(types.BeaconBlockByRootsReq)
|
||||
assert.NoError(t, p2pProvider.Encoding().DecodeWithMaxLength(stream, req))
|
||||
if len(*req) == 0 {
|
||||
return
|
||||
@@ -351,7 +349,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
}
|
||||
_, err := stream.Write([]byte{0x01})
|
||||
assert.NoError(t, err)
|
||||
msg := p2pTypes.ErrorMessage(processorErr.Error())
|
||||
msg := types.ErrorMessage(processorErr.Error())
|
||||
_, err = p2pProvider.Encoding().EncodeWithMaxLength(stream, &msg)
|
||||
assert.NoError(t, err)
|
||||
return
|
||||
@@ -372,7 +370,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
p1.Connect(p2)
|
||||
p2.SetStreamHandler(pcl, knownBlocksProvider(p2, nil))
|
||||
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1]}
|
||||
req := &types.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1]}
|
||||
blocks, err := SendBeaconBlocksByRootRequest(ctx, startup.NewClock(time.Now(), [32]byte{}), p1, p2.PeerID(), req, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 2, len(blocks))
|
||||
@@ -385,7 +383,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
p2.SetStreamHandler(pcl, knownBlocksProvider(p2, nil))
|
||||
|
||||
// No error from block processor.
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1]}
|
||||
req := &types.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1]}
|
||||
blocksFromProcessor := make([]interfaces.ReadOnlySignedBeaconBlock, 0)
|
||||
blocks, err := SendBeaconBlocksByRootRequest(ctx, startup.NewClock(time.Now(), [32]byte{}), p1, p2.PeerID(), req, func(block interfaces.ReadOnlySignedBeaconBlock) error {
|
||||
blocksFromProcessor = append(blocksFromProcessor, block)
|
||||
@@ -403,7 +401,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
p2.SetStreamHandler(pcl, knownBlocksProvider(p2, nil))
|
||||
|
||||
// Send error from block processor.
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1]}
|
||||
req := &types.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1]}
|
||||
errFromProcessor := errors.New("processor error")
|
||||
_, err := SendBeaconBlocksByRootRequest(ctx, startup.NewClock(time.Now(), [32]byte{}), p1, p2.PeerID(), req, func(block interfaces.ReadOnlySignedBeaconBlock) error {
|
||||
return errFromProcessor
|
||||
@@ -418,7 +416,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
p2.SetStreamHandler(pcl, knownBlocksProvider(p2, nil))
|
||||
|
||||
// No cap on max roots.
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1], knownRoots[2], knownRoots[3]}
|
||||
req := &types.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1], knownRoots[2], knownRoots[3]}
|
||||
clock := startup.NewClock(time.Now(), [32]byte{})
|
||||
blocks, err := SendBeaconBlocksByRootRequest(ctx, clock, p1, p2.PeerID(), req, nil)
|
||||
assert.NoError(t, err)
|
||||
@@ -457,7 +455,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
return nil
|
||||
}))
|
||||
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1], knownRoots[2], knownRoots[3]}
|
||||
req := &types.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1], knownRoots[2], knownRoots[3]}
|
||||
blocks, err := SendBeaconBlocksByRootRequest(ctx, startup.NewClock(time.Now(), [32]byte{}), p1, p2.PeerID(), req, nil)
|
||||
assert.ErrorContains(t, expectedErr.Error(), err)
|
||||
assert.Equal(t, 0, len(blocks))
|
||||
@@ -477,7 +475,7 @@ func TestSendRequest_SendBeaconBlocksByRootRequest(t *testing.T) {
|
||||
return nil
|
||||
}))
|
||||
|
||||
req := &p2pTypes.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1], knownRoots[2], knownRoots[3]}
|
||||
req := &types.BeaconBlockByRootsReq{knownRoots[0], knownRoots[1], knownRoots[2], knownRoots[3]}
|
||||
blocks, err := SendBeaconBlocksByRootRequest(ctx, startup.NewClock(time.Now(), [32]byte{}), p1, p2.PeerID(), req, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 3, len(blocks))
|
||||
@@ -520,7 +518,7 @@ func TestBlobValidatorFromRootReq(t *testing.T) {
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
r := p2pTypes.BlobSidecarsByRootReq(c.ids)
|
||||
r := types.BlobSidecarsByRootReq(c.ids)
|
||||
vf := blobValidatorFromRootReq(&r)
|
||||
for _, sc := range c.response {
|
||||
err := vf(sc)
|
||||
@@ -1201,7 +1199,7 @@ func TestSendDataColumnSidecarsByRootRequest(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
nilTestCases := []struct {
|
||||
name string
|
||||
request p2ptypes.DataColumnsByRootIdentifiers
|
||||
request types.DataColumnsByRootIdentifiers
|
||||
}{
|
||||
{
|
||||
name: "nil request",
|
||||
@@ -1209,7 +1207,7 @@ func TestSendDataColumnSidecarsByRootRequest(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "count is 0",
|
||||
request: p2ptypes.DataColumnsByRootIdentifiers{{}, {}},
|
||||
request: types.DataColumnsByRootIdentifiers{{}, {}},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1227,7 +1225,7 @@ func TestSendDataColumnSidecarsByRootRequest(t *testing.T) {
|
||||
cfg.MaxRequestDataColumnSidecars = 4
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
request := p2ptypes.DataColumnsByRootIdentifiers{
|
||||
request := types.DataColumnsByRootIdentifiers{
|
||||
{Columns: []uint64{1, 2, 3}},
|
||||
{Columns: []uint64{4, 5, 6}},
|
||||
}
|
||||
@@ -1324,7 +1322,7 @@ func TestSendDataColumnSidecarsByRootRequest(t *testing.T) {
|
||||
|
||||
blockRoot1, blockRoot2 := expected[0].BlockRoot(), expected[3].BlockRoot()
|
||||
|
||||
sentRequest := p2ptypes.DataColumnsByRootIdentifiers{
|
||||
sentRequest := types.DataColumnsByRootIdentifiers{
|
||||
{BlockRoot: blockRoot1[:], Columns: []uint64{1, 2, 3}},
|
||||
{BlockRoot: blockRoot2[:], Columns: []uint64{1, 2, 3}},
|
||||
}
|
||||
@@ -1335,7 +1333,7 @@ func TestSendDataColumnSidecarsByRootRequest(t *testing.T) {
|
||||
p2.SetStreamHandler(protocol, func(stream network.Stream) {
|
||||
wg.Done()
|
||||
|
||||
requestReceived := new(p2ptypes.DataColumnsByRootIdentifiers)
|
||||
requestReceived := new(types.DataColumnsByRootIdentifiers)
|
||||
err := p2.Encoding().DecodeWithMaxLength(stream, requestReceived)
|
||||
assert.NoError(t, err)
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ const (
|
||||
// Data columns specific.
|
||||
RequireValidFields
|
||||
RequireCorrectSubnet
|
||||
RequireSidecarRootAndSignatureAligned
|
||||
)
|
||||
|
||||
var allBlobSidecarRequirements = []Requirement{
|
||||
|
||||
@@ -39,22 +39,15 @@ var (
|
||||
RequireSidecarProposerExpected,
|
||||
}
|
||||
|
||||
// ByRangeRequestDataColumnSidecarRequirements defines the set of requirements that DataColumnSidecars received
|
||||
// via the by range request must satisfy in order to upgrade an RODataColumn to a VerifiedRODataColumn.
|
||||
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/p2p-interface.md#datacolumnsidecarsbyrange-v1
|
||||
ByRangeRequestDataColumnSidecarRequirements = []Requirement{
|
||||
RequireValidFields,
|
||||
RequireSidecarInclusionProven,
|
||||
RequireSidecarKzgProofVerified,
|
||||
}
|
||||
|
||||
// ByRootRequestDataColumnSidecarRequirements defines the set of requirements that DataColumnSidecars received
|
||||
// via the by root request must satisfy in order to upgrade an RODataColumn to a VerifiedRODataColumn.
|
||||
// RPCDataColumnSidecarRequirements defines the set of requirements that DataColumnSidecars received
|
||||
// via RPC request must satisfy in order to upgrade an RODataColumn to a VerifiedRODataColumn.
|
||||
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/p2p-interface.md#datacolumnsidecarsbyroot-v1
|
||||
ByRootRequestDataColumnSidecarRequirements = []Requirement{
|
||||
// https://github.com/ethereum/consensus-specs/blob/master/specs/fulu/p2p-interface.md#datacolumnsidecarsbyrange-v1
|
||||
RPCDataColumnSidecarRequirements = []Requirement{
|
||||
RequireValidFields,
|
||||
RequireSidecarInclusionProven,
|
||||
RequireSidecarKzgProofVerified,
|
||||
RequireSidecarRootAndSignatureAligned,
|
||||
}
|
||||
|
||||
// SpectestDataColumnSidecarRequirements is used by the forkchoice spectests when verifying data columns used in the on_block tests.
|
||||
@@ -508,20 +501,54 @@ func (dv *RODataColumnsVerifier) SidecarProposerExpected(ctx context.Context) (e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dv *RODataColumnsVerifier) SidecarRootAndSignatureAligned(roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock) (err error) {
|
||||
if ok, err := dv.results.cached(RequireSidecarRootAndSignatureAligned); ok {
|
||||
return err
|
||||
}
|
||||
|
||||
defer dv.recordResult(RequireSidecarRootAndSignatureAligned, &err)
|
||||
|
||||
for _, dataColumn := range dv.dataColumns {
|
||||
// Check if we know the corresponding RO block.
|
||||
root := dataColumn.BlockRoot()
|
||||
roBlock, ok := roBlockByRoot[root]
|
||||
if !ok {
|
||||
return columnErrBuilder(errors.Errorf("no ro block found for data column with root %#x", root))
|
||||
}
|
||||
|
||||
// Check if the signature aligns.
|
||||
sidecarSignature := bytesutil.ToBytes96(dataColumn.SignedBlockHeader.Signature)
|
||||
blockSignature := roBlock.Signature()
|
||||
|
||||
if sidecarSignature != blockSignature {
|
||||
return columnErrBuilder(errUnalignedRootAndSignature)
|
||||
}
|
||||
|
||||
// Check if the root aligns.
|
||||
// Note, this should always be true since we used the root to lookup the RO block.
|
||||
blockRoot := roBlock.Root()
|
||||
if root != blockRoot {
|
||||
return columnErrBuilder(errUnalignedRootAndSignature)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// state retrieves the state of the corresponding root from the cache if possible, else retrieves it from the state by rooter.
|
||||
func (dv *RODataColumnsVerifier) state(ctx context.Context, root [fieldparams.RootLength]byte) (state.BeaconState, error) {
|
||||
// If the parent root is already in the cache, return it.
|
||||
// If the root is already in the cache, return it.
|
||||
if st, ok := dv.stateByRoot[root]; ok {
|
||||
return st, nil
|
||||
}
|
||||
|
||||
// Retrieve the parent state from the state by rooter.
|
||||
// Retrieve the state from the state by rooter.
|
||||
st, err := dv.sr.StateByRoot(ctx, root)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "state by root")
|
||||
}
|
||||
|
||||
// Store the parent state in the cache.
|
||||
// Store the state in the cache.
|
||||
dv.stateByRoot[root] = st
|
||||
|
||||
return st, nil
|
||||
|
||||
@@ -933,6 +933,77 @@ func TestDataColumnsSidecarProposerExpected(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSidecarRootAndSignatureAligned(t *testing.T) {
|
||||
const (
|
||||
columnSlot = 1
|
||||
blobCount = 1
|
||||
)
|
||||
|
||||
parentRoot := [fieldparams.RootLength]byte{}
|
||||
columns := GenerateTestDataColumns(t, parentRoot, columnSlot, blobCount)
|
||||
firstColumn := columns[0]
|
||||
|
||||
t.Run("unknown block", func(t *testing.T) {
|
||||
verifier := new(Initializer).NewDataColumnsVerifier(columns, RPCDataColumnSidecarRequirements)
|
||||
err := verifier.SidecarRootAndSignatureAligned(nil)
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("signatures mismatch", func(t *testing.T) {
|
||||
signedBeaconBlockPb := util.NewBeaconBlock()
|
||||
originalSignature := firstColumn.SignedBlockHeader.Signature
|
||||
alteredSignature := make([]byte, len(originalSignature))
|
||||
copy(alteredSignature, originalSignature)
|
||||
alteredSignature[0] ^= 0xFF // Alter the signature
|
||||
signedBeaconBlockPb.Signature = alteredSignature
|
||||
|
||||
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
||||
require.NoError(t, err)
|
||||
|
||||
roBlock, err := blocks.NewROBlock(signedBeaconBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
verifier := new(Initializer).NewDataColumnsVerifier(columns, RPCDataColumnSidecarRequirements)
|
||||
err = verifier.SidecarRootAndSignatureAligned(map[[fieldparams.RootLength]byte]blocks.ROBlock{
|
||||
firstColumn.BlockRoot(): roBlock,
|
||||
})
|
||||
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("roots mismatch", func(t *testing.T) {
|
||||
signedBeaconBlockPb := util.NewBeaconBlock()
|
||||
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
||||
require.NoError(t, err)
|
||||
|
||||
roBlock, err := blocks.NewROBlock(signedBeaconBlock)
|
||||
require.NoError(t, err)
|
||||
|
||||
verifier := new(Initializer).NewDataColumnsVerifier(columns, RPCDataColumnSidecarRequirements)
|
||||
err = verifier.SidecarRootAndSignatureAligned(map[[fieldparams.RootLength]byte]blocks.ROBlock{
|
||||
firstColumn.BlockRoot(): roBlock,
|
||||
})
|
||||
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
|
||||
t.Run("nominal", func(t *testing.T) {
|
||||
signedBeaconBlockPb := util.NewBeaconBlock()
|
||||
signedBeaconBlock, err := blocks.NewSignedBeaconBlock(signedBeaconBlockPb)
|
||||
require.NoError(t, err)
|
||||
|
||||
roBlock, err := blocks.NewROBlockWithRoot(signedBeaconBlock, firstColumn.BlockRoot())
|
||||
require.NoError(t, err)
|
||||
|
||||
verifier := new(Initializer).NewDataColumnsVerifier(columns, RPCDataColumnSidecarRequirements)
|
||||
err = verifier.SidecarRootAndSignatureAligned(map[[fieldparams.RootLength]byte]blocks.ROBlock{
|
||||
roBlock.Root(): roBlock,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestColumnRequirementSatisfaction(t *testing.T) {
|
||||
const (
|
||||
columnSlot = 1
|
||||
|
||||
@@ -69,6 +69,10 @@ var (
|
||||
// errBatchBlockRootMismatch is returned by VerifiedROBlobs in the scenario where the root of the given signed block
|
||||
// does not match the block header in one of the corresponding sidecars.
|
||||
errBatchBlockRootMismatch = errors.Join(ErrBlobInvalid, errors.New("sidecar block header root does not match signed block"))
|
||||
|
||||
// errUnalignedRootAndSignature is returned by VerifiedRODataColumns when none of the provided RO blocks
|
||||
// align with the sidecar block header root and signature.
|
||||
errUnalignedRootAndSignature = errors.Join(ErrBlobInvalid, errors.New("sidecar block header root and signature do not align with any provided ro blocks"))
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -49,6 +49,7 @@ type DataColumnsVerifier interface {
|
||||
SidecarInclusionProven() error
|
||||
SidecarKzgProofVerified() error
|
||||
SidecarProposerExpected(ctx context.Context) error
|
||||
SidecarRootAndSignatureAligned(roBlockByRoot map[[fieldparams.RootLength]byte]blocks.ROBlock) error
|
||||
}
|
||||
|
||||
// NewDataColumnsVerifier is a function signature that can be used to mock a setup where a
|
||||
|
||||
@@ -79,18 +79,19 @@ func (*MockBlobVerifier) SatisfyRequirement(_ Requirement) {}
|
||||
// --------------------
|
||||
|
||||
type MockDataColumnsVerifier struct {
|
||||
ErrValidFields error
|
||||
ErrCorrectSubnet error
|
||||
ErrNotFromFutureSlot error
|
||||
ErrSlotAboveFinalized error
|
||||
ErrSidecarParentSeen error
|
||||
ErrSidecarParentValid error
|
||||
ErrValidProposerSignature error
|
||||
ErrSidecarParentSlotLower error
|
||||
ErrSidecarDescendsFromFinalized error
|
||||
ErrSidecarInclusionProven error
|
||||
ErrSidecarKzgProofVerified error
|
||||
ErrSidecarProposerExpected error
|
||||
ErrValidFields error
|
||||
ErrCorrectSubnet error
|
||||
ErrNotFromFutureSlot error
|
||||
ErrSlotAboveFinalized error
|
||||
ErrSidecarParentSeen error
|
||||
ErrSidecarParentValid error
|
||||
ErrValidProposerSignature error
|
||||
ErrSidecarParentSlotLower error
|
||||
ErrSidecarDescendsFromFinalized error
|
||||
ErrSidecarInclusionProven error
|
||||
ErrSidecarKzgProofVerified error
|
||||
ErrSidecarProposerExpected error
|
||||
ErrSidecarRootAndSignatureAligned error
|
||||
}
|
||||
|
||||
var _ DataColumnsVerifier = &MockDataColumnsVerifier{}
|
||||
@@ -148,3 +149,7 @@ func (m *MockDataColumnsVerifier) SidecarKzgProofVerified() error {
|
||||
func (m *MockDataColumnsVerifier) SidecarProposerExpected(_ context.Context) error {
|
||||
return m.ErrSidecarProposerExpected
|
||||
}
|
||||
|
||||
func (m *MockDataColumnsVerifier) SidecarRootAndSignatureAligned(_ map[[fieldparams.RootLength]byte]blocks.ROBlock) error {
|
||||
return m.ErrSidecarRootAndSignatureAligned
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user