github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/validate_beacon_attestation_test.go (about) 1 package sync 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "testing" 8 "time" 9 10 lru "github.com/hashicorp/golang-lru" 11 pubsub "github.com/libp2p/go-libp2p-pubsub" 12 pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb" 13 "github.com/prysmaticlabs/go-bitfield" 14 mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing" 15 "github.com/prysmaticlabs/prysm/beacon-chain/core/helpers" 16 dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing" 17 p2ptest "github.com/prysmaticlabs/prysm/beacon-chain/p2p/testing" 18 mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing" 19 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 20 "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper" 21 "github.com/prysmaticlabs/prysm/shared/bytesutil" 22 "github.com/prysmaticlabs/prysm/shared/params" 23 "github.com/prysmaticlabs/prysm/shared/testutil" 24 "github.com/prysmaticlabs/prysm/shared/testutil/require" 25 ) 26 27 func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) { 28 ctx := context.Background() 29 p := p2ptest.NewTestP2P(t) 30 db := dbtest.SetupDB(t) 31 chain := &mockChain.ChainService{ 32 // 1 slot ago. 33 Genesis: time.Now().Add(time.Duration(-1*int64(params.BeaconConfig().SecondsPerSlot)) * time.Second), 34 ValidatorsRoot: [32]byte{'A'}, 35 ValidAttestation: true, 36 } 37 38 c, err := lru.New(10) 39 require.NoError(t, err) 40 s := &Service{ 41 cfg: &Config{ 42 InitialSync: &mockSync.Sync{IsSyncing: false}, 43 P2P: p, 44 DB: db, 45 Chain: chain, 46 AttestationNotifier: (&mockChain.ChainService{}).OperationNotifier(), 47 }, 48 blkRootToPendingAtts: make(map[[32]byte][]*ethpb.SignedAggregateAttestationAndProof), 49 seenUnAggregatedAttestationCache: c, 50 } 51 err = s.initCaches() 52 require.NoError(t, err) 53 54 invalidRoot := [32]byte{'A', 'B', 'C', 'D'} 55 s.setBadBlock(ctx, invalidRoot) 56 57 digest, err := s.forkDigest() 58 require.NoError(t, err) 59 60 blk := testutil.NewBeaconBlock() 61 blk.Block.Slot = 1 62 require.NoError(t, db.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(blk))) 63 64 validBlockRoot, err := blk.Block.HashTreeRoot() 65 require.NoError(t, err) 66 chain.FinalizedCheckPoint = ðpb.Checkpoint{ 67 Root: validBlockRoot[:], 68 Epoch: 0, 69 } 70 71 validators := uint64(64) 72 savedState, keys := testutil.DeterministicGenesisState(t, validators) 73 require.NoError(t, savedState.SetSlot(1)) 74 require.NoError(t, db.SaveState(context.Background(), savedState, validBlockRoot)) 75 chain.State = savedState 76 77 tests := []struct { 78 name string 79 msg *ethpb.Attestation 80 topic string 81 validAttestationSignature bool 82 want bool 83 }{ 84 { 85 name: "valid attestation signature", 86 msg: ðpb.Attestation{ 87 AggregationBits: bitfield.Bitlist{0b101}, 88 Data: ðpb.AttestationData{ 89 BeaconBlockRoot: validBlockRoot[:], 90 CommitteeIndex: 0, 91 Slot: 1, 92 Target: ðpb.Checkpoint{ 93 Epoch: 0, 94 Root: validBlockRoot[:], 95 }, 96 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 97 }, 98 }, 99 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 100 validAttestationSignature: true, 101 want: true, 102 }, 103 { 104 name: "valid attestation signature with nil topic", 105 msg: ðpb.Attestation{ 106 AggregationBits: bitfield.Bitlist{0b101}, 107 Data: ðpb.AttestationData{ 108 BeaconBlockRoot: validBlockRoot[:], 109 CommitteeIndex: 0, 110 Slot: 1, 111 Target: ðpb.Checkpoint{ 112 Epoch: 0, 113 Root: validBlockRoot[:], 114 }, 115 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 116 }, 117 }, 118 topic: "", 119 validAttestationSignature: true, 120 want: false, 121 }, 122 { 123 name: "bad target epoch", 124 msg: ðpb.Attestation{ 125 AggregationBits: bitfield.Bitlist{0b101}, 126 Data: ðpb.AttestationData{ 127 BeaconBlockRoot: validBlockRoot[:], 128 CommitteeIndex: 0, 129 Slot: 1, 130 Target: ðpb.Checkpoint{ 131 Epoch: 10, 132 Root: validBlockRoot[:], 133 }, 134 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 135 }, 136 }, 137 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 138 validAttestationSignature: true, 139 want: false, 140 }, 141 { 142 name: "already seen", 143 msg: ðpb.Attestation{ 144 AggregationBits: bitfield.Bitlist{0b101}, 145 Data: ðpb.AttestationData{ 146 BeaconBlockRoot: validBlockRoot[:], 147 CommitteeIndex: 0, 148 Slot: 1, 149 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 150 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 151 }, 152 }, 153 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 154 validAttestationSignature: true, 155 want: false, 156 }, 157 { 158 name: "invalid beacon block", 159 msg: ðpb.Attestation{ 160 AggregationBits: bitfield.Bitlist{0b101}, 161 Data: ðpb.AttestationData{ 162 BeaconBlockRoot: invalidRoot[:], 163 CommitteeIndex: 0, 164 Slot: 1, 165 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 166 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 167 }, 168 }, 169 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 170 validAttestationSignature: true, 171 want: false, 172 }, 173 { 174 name: "committee index exceeds committee length", 175 msg: ðpb.Attestation{ 176 AggregationBits: bitfield.Bitlist{0b101}, 177 Data: ðpb.AttestationData{ 178 BeaconBlockRoot: validBlockRoot[:], 179 CommitteeIndex: 4, 180 Slot: 1, 181 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 182 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 183 }, 184 }, 185 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_2", digest), 186 validAttestationSignature: true, 187 want: false, 188 }, 189 { 190 name: "wrong committee index", 191 msg: ðpb.Attestation{ 192 AggregationBits: bitfield.Bitlist{0b101}, 193 Data: ðpb.AttestationData{ 194 BeaconBlockRoot: validBlockRoot[:], 195 CommitteeIndex: 2, 196 Slot: 1, 197 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 198 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 199 }, 200 }, 201 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_2", digest), 202 validAttestationSignature: true, 203 want: false, 204 }, 205 { 206 name: "already aggregated", 207 msg: ðpb.Attestation{ 208 AggregationBits: bitfield.Bitlist{0b1011}, 209 Data: ðpb.AttestationData{ 210 BeaconBlockRoot: validBlockRoot[:], 211 CommitteeIndex: 1, 212 Slot: 1, 213 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 214 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 215 }, 216 }, 217 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 218 validAttestationSignature: true, 219 want: false, 220 }, 221 { 222 name: "missing block", 223 msg: ðpb.Attestation{ 224 AggregationBits: bitfield.Bitlist{0b101}, 225 Data: ðpb.AttestationData{ 226 BeaconBlockRoot: bytesutil.PadTo([]byte("missing"), 32), 227 CommitteeIndex: 1, 228 Slot: 1, 229 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 230 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 231 }, 232 }, 233 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 234 validAttestationSignature: true, 235 want: false, 236 }, 237 { 238 name: "invalid attestation", 239 msg: ðpb.Attestation{ 240 AggregationBits: bitfield.Bitlist{0b101}, 241 Data: ðpb.AttestationData{ 242 BeaconBlockRoot: validBlockRoot[:], 243 CommitteeIndex: 1, 244 Slot: 1, 245 Target: ðpb.Checkpoint{Root: make([]byte, 32)}, 246 Source: ðpb.Checkpoint{Root: make([]byte, 32)}, 247 }, 248 }, 249 topic: fmt.Sprintf("/eth2/%x/beacon_attestation_1", digest), 250 validAttestationSignature: false, 251 want: false, 252 }, 253 } 254 255 for _, tt := range tests { 256 t.Run(tt.name, func(t *testing.T) { 257 helpers.ClearCache() 258 chain.ValidAttestation = tt.validAttestationSignature 259 if tt.validAttestationSignature { 260 com, err := helpers.BeaconCommitteeFromState(savedState, tt.msg.Data.Slot, tt.msg.Data.CommitteeIndex) 261 require.NoError(t, err) 262 domain, err := helpers.Domain(savedState.Fork(), tt.msg.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, savedState.GenesisValidatorRoot()) 263 require.NoError(t, err) 264 attRoot, err := helpers.ComputeSigningRoot(tt.msg.Data, domain) 265 require.NoError(t, err) 266 for i := 0; ; i++ { 267 if tt.msg.AggregationBits.BitAt(uint64(i)) { 268 tt.msg.Signature = keys[com[i]].Sign(attRoot[:]).Marshal() 269 break 270 } 271 } 272 } else { 273 tt.msg.Signature = make([]byte, 96) 274 } 275 buf := new(bytes.Buffer) 276 _, err := p.Encoding().EncodeGossip(buf, tt.msg) 277 require.NoError(t, err) 278 m := &pubsub.Message{ 279 Message: &pubsubpb.Message{ 280 Data: buf.Bytes(), 281 Topic: &tt.topic, 282 }, 283 } 284 if tt.topic == "" { 285 m.Message.Topic = nil 286 } 287 received := s.validateCommitteeIndexBeaconAttestation(ctx, "" /*peerID*/, m) == pubsub.ValidationAccept 288 if received != tt.want { 289 t.Fatalf("Did not received wanted validation. Got %v, wanted %v", !tt.want, tt.want) 290 } 291 if tt.want && m.ValidatorData == nil { 292 t.Error("Expected validator data to be set") 293 } 294 }) 295 } 296 }