Skip to content

Commit

Permalink
more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rkapka committed Nov 26, 2024
1 parent d27e587 commit bd59ada
Showing 1 changed file with 93 additions and 70 deletions.
163 changes: 93 additions & 70 deletions beacon-chain/rpc/eth/validator/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,33 @@ func TestGetAggregateAttestation(t *testing.T) {
require.NoError(t, err)
sig := key.Sign([]byte("sig"))

t.Run("V1", func(t *testing.T) {
createAttestation := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte) *ethpbalpha.Attestation {
return &ethpbalpha.Attestation{
AggregationBits: aggregationBits,
Data: createAttestationData(slot, 1, 1, root),
Signature: sig.Marshal(),
}
// It is important to use 0 as the index because that's the only way
// pre and post-Electra attestations can both match,
// which allows us to properly test that attestations from the
// wrong fork are ignored.
committeeIndex := uint64(0)

createAttestation := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte) *ethpbalpha.Attestation {
return &ethpbalpha.Attestation{
AggregationBits: aggregationBits,
Data: createAttestationData(slot, primitives.CommitteeIndex(committeeIndex), root),
Signature: sig.Marshal(),
}
}

createAttestationElectra := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte) *ethpbalpha.AttestationElectra {
committeeBits := bitfield.NewBitvector64()
committeeBits.SetBitAt(committeeIndex, true)

return &ethpbalpha.AttestationElectra{
CommitteeBits: committeeBits,
AggregationBits: aggregationBits,
Data: createAttestationData(slot, primitives.CommitteeIndex(committeeIndex), root),
Signature: sig.Marshal(),
}
}

t.Run("V1", func(t *testing.T) {
aggSlot1_Root1_1 := createAttestation(1, bitfield.Bitlist{0b11100}, root1)
aggSlot1_Root1_2 := createAttestation(1, bitfield.Bitlist{0b10111}, root1)
aggSlot1_Root2 := createAttestation(1, bitfield.Bitlist{0b11100}, root2)
Expand All @@ -84,7 +102,7 @@ func TestGetAggregateAttestation(t *testing.T) {
assert.Equal(t, expectedAggregationBits, attestation.AggregationBits, "Unexpected aggregation bits in attestation")
assert.Equal(t, hexutil.Encode(expectedSig), attestation.Signature, "Signature mismatch")
assert.Equal(t, expectedSlot, attestation.Data.Slot, "Slot mismatch in attestation data")
assert.Equal(t, "1", attestation.Data.CommitteeIndex, "Committee index mismatch")
assert.Equal(t, "0", attestation.Data.CommitteeIndex, "Committee index mismatch")
assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.BeaconBlockRoot, "Beacon block root mismatch")

// Source checkpoint checks
Expand Down Expand Up @@ -207,32 +225,22 @@ func TestGetAggregateAttestation(t *testing.T) {
})
t.Run("V2", func(t *testing.T) {
t.Run("pre-electra", func(t *testing.T) {
createAttestation := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte) *ethpbalpha.Attestation {
return &ethpbalpha.Attestation{
AggregationBits: aggregationBits,
Data: createAttestationData(slot, 1, 1, root),
Signature: sig.Marshal(),
}
}

committeeBits := bitfield.NewBitvector64()
committeeBits.SetBitAt(1, true)

aggSlot1_Root1_1 := createAttestation(1, bitfield.Bitlist{0b11100}, root1)
aggSlot1_Root1_2 := createAttestation(1, bitfield.Bitlist{0b10111}, root1)
aggSlot1_Root2 := createAttestation(1, bitfield.Bitlist{0b11100}, root2)
aggSlot1_Root2_2_electra := &ethpbalpha.AttestationElectra{
CommitteeBits: committeeBits,
AggregationBits: bitfield.Bitlist{0b10111},
Data: createAttestationData(1, 1, 1, root2),
Signature: sig.Marshal(),
}
aggSlot2 := createAttestation(2, bitfield.Bitlist{0b11100}, root1)
unaggSlot3_Root1_1 := createAttestation(3, bitfield.Bitlist{0b11000}, root1)
unaggSlot3_Root1_2 := createAttestation(3, bitfield.Bitlist{0b10100}, root1)
unaggSlot3_Root2 := createAttestation(3, bitfield.Bitlist{0b11000}, root2)
unaggSlot4 := createAttestation(4, bitfield.Bitlist{0b11000}, root1)

// Add one post-electra attestation to ensure that it is being ignored.
// We choose slot 2 where we have one pre-electra attestation with less attestation bits.
postElectraAtt := createAttestationElectra(2, bitfield.Bitlist{0b11111}, root1)

compareResult := func(
t *testing.T,
attestation structs.Attestation,
Expand All @@ -244,7 +252,7 @@ func TestGetAggregateAttestation(t *testing.T) {
assert.Equal(t, expectedAggregationBits, attestation.AggregationBits, "Unexpected aggregation bits in attestation")
assert.Equal(t, hexutil.Encode(expectedSig), attestation.Signature, "Signature mismatch")
assert.Equal(t, expectedSlot, attestation.Data.Slot, "Slot mismatch in attestation data")
assert.Equal(t, "1", attestation.Data.CommitteeIndex, "Committee index mismatch")
assert.Equal(t, "0", attestation.Data.CommitteeIndex, "Committee index mismatch")
assert.Equal(t, hexutil.Encode(expectedRoot), attestation.Data.BeaconBlockRoot, "Beacon block root mismatch")

// Source checkpoint checks
Expand All @@ -263,18 +271,49 @@ func TestGetAggregateAttestation(t *testing.T) {
unagg, err := pool.UnaggregatedAttestations()
require.NoError(t, err)
require.Equal(t, 4, len(unagg), "Expected 4 unaggregated attestations")
require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2, aggSlot1_Root2_2_electra}), "Failed to save aggregated attestations")
require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2, postElectraAtt}), "Failed to save aggregated attestations")
agg := pool.AggregatedAttestations()
require.Equal(t, 5, len(agg), "Expected 5 aggregated attestations, 4 pre electra and 1 post electra")
s := &Server{
AttestationsPool: pool,
}

t.Run("non-matching attestation request", func(t *testing.T) {
reqRoot, err := aggSlot2.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

s.GetAggregateAttestationV2(writer, request)
assert.Equal(t, http.StatusNotFound, writer.Code, "Expected HTTP status NotFound for non-matching request")
})
t.Run("1 matching aggregated attestation", func(t *testing.T) {
reqRoot, err := aggSlot2.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

s.GetAggregateAttestationV2(writer, request)
require.Equal(t, http.StatusOK, writer.Code, "Expected HTTP status OK")

var resp structs.AggregateAttestationResponse
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp), "Failed to unmarshal response")
require.NotNil(t, resp.Data, "Response data should not be nil")

var attestation structs.Attestation
require.NoError(t, json.Unmarshal(resp.Data, &attestation), "Failed to unmarshal attestation data")

compareResult(t, attestation, "2", hexutil.Encode(aggSlot2.AggregationBits), root1, sig.Marshal())
})
t.Run("multiple matching aggregated attestations - return the one with most bits", func(t *testing.T) {
reqRoot, err := aggSlot1_Root1_1.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=1"
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

Expand All @@ -292,32 +331,18 @@ func TestGetAggregateAttestation(t *testing.T) {
})
})
t.Run("post-electra", func(t *testing.T) {
createAttestation := func(slot primitives.Slot, aggregationBits bitfield.Bitlist, root []byte, bits uint64) *ethpbalpha.AttestationElectra {
committeeBits := bitfield.NewBitvector64()
committeeBits.SetBitAt(bits, true)

return &ethpbalpha.AttestationElectra{
CommitteeBits: committeeBits,
AggregationBits: aggregationBits,
Data: createAttestationData(slot, 0, 1, root),
Signature: sig.Marshal(),
}
}

aggSlot1_Root1_1 := createAttestation(1, bitfield.Bitlist{0b11100}, root1, 1)
aggSlot1_Root1_2 := createAttestation(1, bitfield.Bitlist{0b10111}, root1, 1)
aggSlot1_Root2 := createAttestation(1, bitfield.Bitlist{0b11100}, root2, 1)
// Added one pre-electra agg attestation to ensure that it is being ignored.
aggSlot1_Root2_2 := &ethpbalpha.Attestation{
AggregationBits: bitfield.Bitlist{0b10111},
Data: createAttestationData(1, 1, 1, root2),
Signature: sig.Marshal(),
}
aggSlot2 := createAttestation(2, bitfield.Bitlist{0b11100}, root1, 1)
unaggSlot3_Root1_1 := createAttestation(3, bitfield.Bitlist{0b11000}, root1, 1)
unaggSlot3_Root1_2 := createAttestation(3, bitfield.Bitlist{0b10100}, root1, 1)
unaggSlot3_Root2 := createAttestation(3, bitfield.Bitlist{0b11000}, root2, 1)
unaggSlot4 := createAttestation(4, bitfield.Bitlist{0b11000}, root1, 1)
aggSlot1_Root1_1 := createAttestationElectra(1, bitfield.Bitlist{0b11100}, root1)
aggSlot1_Root1_2 := createAttestationElectra(1, bitfield.Bitlist{0b10111}, root1)
aggSlot1_Root2 := createAttestationElectra(1, bitfield.Bitlist{0b11100}, root2)
aggSlot2 := createAttestationElectra(2, bitfield.Bitlist{0b11100}, root1)
unaggSlot3_Root1_1 := createAttestationElectra(3, bitfield.Bitlist{0b11000}, root1)
unaggSlot3_Root1_2 := createAttestationElectra(3, bitfield.Bitlist{0b10100}, root1)
unaggSlot3_Root2 := createAttestationElectra(3, bitfield.Bitlist{0b11000}, root2)
unaggSlot4 := createAttestationElectra(4, bitfield.Bitlist{0b11000}, root1)

// Add one pre-electra attestation to ensure that it is being ignored.
// We choose slot 2 where we have one post-electra attestation with less attestation bits.
preElectraAtt := createAttestation(2, bitfield.Bitlist{0b11111}, root1)

compareResult := func(
t *testing.T,
Expand Down Expand Up @@ -351,7 +376,7 @@ func TestGetAggregateAttestation(t *testing.T) {
unagg, err := pool.UnaggregatedAttestations()
require.NoError(t, err)
require.Equal(t, 4, len(unagg), "Expected 4 unaggregated attestations")
require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2, aggSlot1_Root2_2}), "Failed to save aggregated attestations")
require.NoError(t, pool.SaveAggregatedAttestations([]ethpbalpha.Att{aggSlot1_Root1_1, aggSlot1_Root1_2, aggSlot1_Root2, aggSlot2, preElectraAtt}), "Failed to save aggregated attestations")
agg := pool.AggregatedAttestations()
require.Equal(t, 5, len(agg), "Expected 5 aggregated attestations, 4 electra and 1 pre electra")
bs, err := util.NewBeaconState()
Expand All @@ -372,7 +397,7 @@ func TestGetAggregateAttestation(t *testing.T) {
reqRoot, err := aggSlot2.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=1"
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

Expand All @@ -383,7 +408,7 @@ func TestGetAggregateAttestation(t *testing.T) {
reqRoot, err := aggSlot2.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" + "&committee_index=1"
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=2" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

Expand All @@ -403,7 +428,7 @@ func TestGetAggregateAttestation(t *testing.T) {
reqRoot, err := aggSlot1_Root1_1.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=1"
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=1" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

Expand All @@ -423,7 +448,7 @@ func TestGetAggregateAttestation(t *testing.T) {
reqRoot, err := unaggSlot4.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=4" + "&committee_index=1"
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=4" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

Expand All @@ -442,7 +467,7 @@ func TestGetAggregateAttestation(t *testing.T) {
reqRoot, err := unaggSlot3_Root1_1.Data.HashTreeRoot()
require.NoError(t, err, "Failed to generate attestation data hash tree root")
attDataRoot := hexutil.Encode(reqRoot[:])
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=3" + "&committee_index=1"
url := "http://example.com?attestation_data_root=" + attDataRoot + "&slot=3" + "&committee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()

Expand All @@ -462,27 +487,25 @@ func TestGetAggregateAttestation(t *testing.T) {
expectedSig := bls.AggregateSignatures([]common.Signature{sig1, sig2})
compareResult(t, attestation, "3", hexutil.Encode(bitfield.Bitlist{0b11100}), root1, expectedSig.Marshal(), hexutil.Encode(unaggSlot3_Root1_1.CommitteeBits))
})
t.Run("pre-electra attestation is ignored", func(t *testing.T) {

})
})
})

}

func createAttestationData(
slot primitives.Slot,
committeeIndex primitives.CommitteeIndex,
epoch primitives.Epoch,
root []byte,
) *ethpbalpha.AttestationData {
func createAttestationData(slot primitives.Slot, committeeIndex primitives.CommitteeIndex, root []byte) *ethpbalpha.AttestationData {
return &ethpbalpha.AttestationData{
Slot: slot,
CommitteeIndex: committeeIndex,
BeaconBlockRoot: root,
Source: &ethpbalpha.Checkpoint{
Epoch: epoch,
Epoch: 1,
Root: root,
},
Target: &ethpbalpha.Checkpoint{
Epoch: epoch,
Epoch: 1,
Root: root,
},
}
Expand Down Expand Up @@ -1564,7 +1587,7 @@ func TestProduceSyncCommitteeContribution(t *testing.T) {
SyncCommitteePool: syncCommitteePool,
}
t.Run("ok", func(t *testing.T) {
url := "http://example.com?slot=1&subcommittee_index=1&beacon_block_root=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
url := "http://example.com?slot=1&subcommittee_index=0&beacon_block_root=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
Expand All @@ -1579,7 +1602,7 @@ func TestProduceSyncCommitteeContribution(t *testing.T) {
require.Equal(t, resp.Data.BeaconBlockRoot, "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2")
})
t.Run("no slot provided", func(t *testing.T) {
url := "http://example.com?subcommittee_index=1&beacon_block_root=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
url := "http://example.com?subcommittee_index=0&beacon_block_root=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
Expand All @@ -1603,7 +1626,7 @@ func TestProduceSyncCommitteeContribution(t *testing.T) {
require.ErrorContains(t, "subcommittee_index is required", errors.New(writer.Body.String()))
})
t.Run("no beacon_block_root provided", func(t *testing.T) {
url := "http://example.com?slot=1&subcommittee_index=1"
url := "http://example.com?slot=1&subcommittee_index=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
Expand All @@ -1615,7 +1638,7 @@ func TestProduceSyncCommitteeContribution(t *testing.T) {
require.ErrorContains(t, "Invalid Beacon Block Root: empty hex string", errors.New(writer.Body.String()))
})
t.Run("invalid block root", func(t *testing.T) {
url := "http://example.com?slot=1&subcommittee_index=1&beacon_block_root=0"
url := "http://example.com?slot=1&subcommittee_index=0&beacon_block_root=0"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
Expand All @@ -1627,7 +1650,7 @@ func TestProduceSyncCommitteeContribution(t *testing.T) {
require.ErrorContains(t, "Invalid Beacon Block Root: hex string without 0x prefix", errors.New(writer.Body.String()))
})
t.Run("no committee messages", func(t *testing.T) {
url := "http://example.com?slot=1&subcommittee_index=1&beacon_block_root=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
url := "http://example.com?slot=1&subcommittee_index=0&beacon_block_root=0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
request := httptest.NewRequest(http.MethodGet, url, nil)
writer := httptest.NewRecorder()
writer.Body = &bytes.Buffer{}
Expand Down

0 comments on commit bd59ada

Please sign in to comment.