Compare commits

...

175 Commits

Author SHA1 Message Date
rauljordan
7dd1ce957f beacon 2021-09-29 14:57:06 -04:00
rauljordan
673a845918 testing 2021-09-29 14:50:43 -04:00
rauljordan
15a024f171 e2e 2021-09-29 14:49:07 -04:00
rauljordan
618e7d8f89 confs 2021-09-29 14:45:55 -04:00
Raul Jordan
df33ce3309 Remaining Slasher Beacon Node Changes (#9701)
* slasher beacon node changes

* remaining beacon node items

* moar changes

* gaz

* flag fix

* rem slashable

* builds

* imports

* fix up

* pruning faster test

* deepsource

* fix wrong item

* node node feature flags

* broken test

* preston review

* more preston comments

* comment

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-09-29 18:17:37 +00:00
terence tsao
86efa87101 Refactor sync and participation field roots (#9703)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-09-29 17:46:51 +00:00
Potuz
ff625d55df Use target root for pending attestations in tests instead of unrelated one (#9699)
* Use target root for pending attestations instead of unrelated one

* remove unnecessary block saves

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-09-29 12:27:47 -05:00
Mohamed Zahoor
0678e9f718 finalise deposits before we initialise the node (#9639)
* finalize deposits before we initialize the node

* Update beacon-chain/blockchain/service.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* Update beacon-chain/blockchain/service.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* moved this when intiializing caches

* added test case

* satisfy deepsource

* fix gazel

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
Co-authored-by: Nishant Das <nishdas93@gmail.com>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-09-29 15:43:24 +00:00
Nishant Das
10251c4191 increase size (#9702) 2021-09-29 10:01:10 -05:00
Potuz
861c2f5120 remove unnecessary asserts from tests (#9700) 2021-09-29 22:17:06 +08:00
Raul Jordan
26de0f1358 rem sim 2021-09-28 22:31:49 -04:00
Raul Jordan
5f38167cd9 sync 2021-09-28 22:30:46 -04:00
rauljordan
a0193ca90c sync 2021-09-28 17:12:51 -04:00
Raul Jordan
0fc5b27195 Merge branch 'develop' into feature/slasher 2021-09-28 14:18:06 -05:00
rauljordan
2a9a978fc6 fix conflicts 2021-09-28 15:09:42 -04:00
Raul Jordan
9a78ce007a fix conflicts 2021-09-13 15:36:35 -04:00
rauljordan
16febfe6d9 merge develop 2021-08-24 16:05:07 -05:00
rauljordan
db57c45ec9 merge develop 2021-08-24 16:03:47 -05:00
Raul Jordan
0d99862e42 sync develop 2021-08-17 11:21:11 -06:00
Raul Jordan
a4f35f4b09 sync develop 2021-08-10 14:42:24 -06:00
Raul Jordan
ebb1fe80f9 Merge branch 'develop' into feature/slasher 2021-08-05 14:52:05 -05:00
Raul Jordan
ab071834fb fix some tests 2021-08-05 13:49:32 -06:00
Raul Jordan
e27fb164a3 Merge branch 'feature/slasher' of github.com:prysmaticlabs/prysm into feature/slasher 2021-08-05 11:48:22 -06:00
Raul Jordan
7b807a6c01 fix build 2021-08-05 11:47:51 -06:00
Raul Jordan
33e6908c71 Merge branch 'develop' into feature/slasher 2021-08-05 12:46:29 -05:00
Raul Jordan
bac54f53ab gaz 2021-08-05 11:40:18 -06:00
Raul Jordan
960d39c859 fix deepsource 2021-08-05 10:59:23 -06:00
Raul Jordan
fc951b4416 regen protos 2021-08-05 10:30:53 -06:00
Raul Jordan
4d2a01e6df fix conflicts 2021-08-05 09:57:29 -06:00
Raul Jordan
3121501e80 remove old slasher 2021-08-05 08:56:02 -06:00
Raul Jordan
65656045f9 resolve more conflicts 2021-08-04 22:45:52 -06:00
Raul Jordan
59b38ed293 merge develop 2021-08-04 21:33:42 -06:00
Raul Jordan
963f61f1fb End-to-End Test Suite For Synced Slasher Node (#9169)
* begin slasher-sync-e2e

* all changes required for slasher sync e2e

* gaz

* commentary

* false test deposits

* skip e2e until functionality is checked in
2021-08-02 08:44:02 -05:00
Raul Jordan
1e8720057e Benchmarks for Detect Slashable Attestations (#9175)
* atts benchmark

* require errcheck

* handle errvalues
2021-07-13 13:27:34 -05:00
Raul Jordan
2fa80c35dc Merge branch 'develop' into feature/slasher 2021-07-13 09:47:02 -04:00
Raul Jordan
96852134ab add sync checker in node startup for slasher 2021-07-08 13:55:59 -05:00
Raul Jordan
2606935c42 Merge branch 'develop' into feature/slasher 2021-07-08 13:31:49 -05:00
Raul Jordan
c6ca50e766 pass missing tests 2021-07-08 13:30:53 -05:00
Raul Jordan
3433002bae Merge branch 'develop' into feature/slasher 2021-07-08 10:52:18 -05:00
Raul Jordan
ce9df503b3 Reduce Duplication of Attestations in SlasherDB (#9130)
* remove fastsum of attesting indices

* gazelle
2021-07-07 16:29:54 +00:00
Raul Jordan
b93d925047 do not run slasher if syncing the chain 2021-07-07 11:29:07 -05:00
Raul Jordan
1df73a698b gaz 2021-07-07 09:27:17 -05:00
Raul Jordan
ca2461491c merge develop 2021-07-07 09:10:01 -05:00
Raul Jordan
83fb66b9d5 allow compile 2021-06-30 15:33:37 -05:00
rauljordan
ab3ffb5d38 info verbosity for pruning 2021-06-30 12:08:11 -05:00
Raul Jordan
28fbbbdf7f display pruned items 2021-06-29 21:23:58 -05:00
Raul Jordan
eb612d81b1 Parallelized Double Vote Detection in Slasher With Disk-Space Efficient Schema (#9086)
* use errgroup to optimize double vote detection and use a more disk-space-efficient schema

* errgroup find
2021-06-23 21:41:39 +00:00
Raul Jordan
601fbbfb3a merge in develop 2021-06-23 15:21:05 -06:00
Raul Jordan
f4d3eec431 amend import not found 2021-06-18 09:34:00 -05:00
Raul Jordan
b3ffac459a add slasher handler 2021-06-18 09:26:09 -05:00
Raul Jordan
2e1b8190eb merge develop 2021-06-18 09:25:19 -05:00
Raul Jordan
bf14b28ca9 Merge branch 'develop' into feature/slasher 2021-06-17 20:24:51 -05:00
Raul Jordan
b4b6f25386 improve tests to use head slot 2021-06-17 14:50:07 -05:00
rauljordan
f5f95d8f99 sync with develop 2021-06-17 13:39:49 -05:00
Raul Jordan
d93369294c Merge branch 'develop' into feature/slasher 2021-06-11 14:03:14 -05:00
Raul Jordan
ad0332ba41 build 2021-06-10 16:58:15 -05:00
Raul Jordan
18d00724b2 remove ethereumapis 2021-06-10 16:46:08 -05:00
Raul Jordan
a21b98bfd3 merge develop 2021-06-10 16:29:23 -05:00
Raul Jordan
35b853c958 Merge branch 'develop' into feature/slasher 2021-05-21 14:35:34 -05:00
Raul Jordan
401f73d341 Merge branch 'develop' into feature/slasher 2021-05-20 11:11:08 -05:00
Raul Jordan
403389a0d8 Use Pruning Sliding Window for Slasher (#8911)
* proper sliding window pruning for slasher

* test passing for attestation pruning

* proposals get pruned

* amend pruning tests

* added log

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Radosław Kapka <rkapka@wp.pl>

* remaining comments

* Update beacon-chain/db/slasherkv/slasher.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* preston comments

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-05-20 11:10:51 -05:00
Raul Jordan
8c5d577636 merge develop 2021-05-18 18:59:34 -05:00
Raul Jordan
f4d54506a0 Merge branch 'develop' into feature/slasher 2021-05-07 16:18:53 -05:00
Raul Jordan
44f6ec48b8 Merge branch 'develop' into feature/slasher 2021-05-05 12:14:35 -05:00
Raul Jordan
2958c84872 Ensure Validator Has No Breaking Changes in New Slasher (#8862)
* add new flag to prevent breaking changes

* pass tests

* gaz

* rename to old slasher

* rem deprecation

* passing tests
2021-05-05 12:14:16 -05:00
rauljordan
e9d670f16f build file confs 2021-05-04 11:42:25 -05:00
rauljordan
7194d025ba fix up conflicts 2021-05-04 11:38:03 -05:00
Raul Jordan
0776639772 Merge branch 'develop' into feature/slasher 2021-05-03 20:32:35 -05:00
Raul Jordan
68d43a9e90 fix confs 2021-05-03 15:44:47 -05:00
Raul Jordan
e18cca94c9 Merge branch 'develop' into feature/slasher 2021-04-28 09:41:32 -05:00
Raul Jordan
08df279330 Merge branch 'develop' into feature/slasher 2021-04-27 19:03:04 -05:00
rauljordan
c80fc63c9f fix sim 2021-04-23 14:40:25 -05:00
rauljordan
1df189339a Merge branch 'develop' into feature/slasher 2021-04-23 12:06:25 -05:00
rauljordan
c0246bd82e add back ensure embedded 2021-04-23 10:35:29 -05:00
rauljordan
12ed20f341 fix e2e conflicts 2021-04-23 09:56:31 -05:00
terence tsao
9824e17c83 Merge branch 'develop' into feature/slasher 2021-04-22 09:46:37 -07:00
Raul Jordan
f4e247808a Merge branch 'develop' into feature/slasher 2021-04-21 08:46:30 -05:00
Raul Jordan
8dcfa40807 Merge branch 'develop' into feature/slasher 2021-04-20 10:00:42 -05:00
Raul Jordan
89ee961354 Merge branch 'develop' into feature/slasher 2021-04-19 08:39:43 -05:00
rauljordan
ad30274a2d gaz 2021-04-16 15:29:27 -05:00
rauljordan
91ce227966 passthrough 2021-04-16 14:53:14 -05:00
rauljordan
dd4154aed9 fmt 2021-04-16 14:48:09 -05:00
rauljordan
6f97ff2219 merge develop 2021-04-16 14:45:28 -05:00
Raul Jordan
ac44476977 Batch Pruning for Optimized Slasher (#8764)
* cursor-based pruning

* pruning logic with commentary

* full algo

* proper conditional

* better log

* edit log

* improvements to alg

* it worked

* begin same pruning process for attestations, correctness first, then deduplication later

* slasher prune atts test

* better prune

* pass pruning tests

* gaz

* fix slasher build

* ineff assing

* remove irrelevant test

* highest attestations passing

* Victor's suggestion

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* Update beacon-chain/db/slasherkv/pruning.go

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>

* added test main to file

Co-authored-by: Victor Farazdagi <simple.square@gmail.com>
2021-04-16 14:40:01 -05:00
Raul Jordan
6cecb79988 Optimized Slasher Should Use its Own DB File (#8749)
* unique database for slasher content

* use beacon db for simulator for stategen

* build

* prom

* gaz

* change viz

* remove duplicate metrics collection

* revert

* revert
2021-04-13 21:59:04 -05:00
Raul Jordan
67ac7a7455 Merge branch 'develop' into feature/slasher 2021-04-13 20:38:59 -05:00
Raul Jordan
4e6981374e Merge branch 'develop' into feature/slasher 2021-04-13 12:59:43 -05:00
Raul Jordan
21b33d3883 Merge branch 'develop' into feature/slasher 2021-04-10 11:37:19 -05:00
Raul Jordan
ca5527e331 Merge branch 'develop' into feature/slasher 2021-04-09 15:45:39 -05:00
Raul Jordan
cb0450eb23 Save Attestations in Slasher's History During Remote Protection (#8726)
* mark attestations

* pass tests

* comment
2021-04-09 15:45:27 -05:00
Raul Jordan
9a75bb9d5a Merge branch 'develop' into feature/slasher 2021-04-08 09:32:41 -05:00
rauljordan
71f9b8be87 fix build 2021-04-08 09:28:45 -05:00
rauljordan
03b1bc12a6 fix confs 2021-04-08 09:14:04 -05:00
rauljordan
3a7ce95dc2 Merge branch 'develop' of github.com:prysmaticlabs/prysm into develop 2021-04-08 09:11:22 -05:00
Raul Jordan
dfb0209f01 Use Optimized Slasher in E2E Code (#8718)
* new slasher in e2e

* propose block investigation

* slasher e2e tests all passes
2021-04-08 08:59:04 -05:00
Raul Jordan
5a22c5c2b0 Optimized Slasher Better DB Schema (#8720)
* optimize

* optimized db storage

* comments

* ivan comments
2021-04-08 07:43:59 -05:00
Raul Jordan
7734ae1006 Fix Optimized Remote Slashing Protection (#8719)
* fix remote slashing response

* gaz
2021-04-07 14:17:13 -05:00
Raul Jordan
71ac917ba8 Space Efficiency in Slasher DB Schema, Add More Metrics (#8701)
* add new encoding functions to save on space

* slasher more space efficient

* opt and fix slasher tests

* merge

* compile

* unused funcs

* broken tests

* use consistent, history length

* tests passing

* use types.epoch

* microopt
2021-04-06 08:46:19 -05:00
Raul Jordan
8836445dff conflict 2021-04-05 15:00:13 -05:00
rauljordan
661bf55961 deep source issues 2021-04-05 11:46:03 -05:00
Raul Jordan
48d1b8766e Merge branch 'feature/slasher' of github.com:prysmaticlabs/prysm into feature/slasher 2021-03-30 16:04:44 -05:00
Raul Jordan
1127851899 more realistic params for slasher e2e 2021-03-30 16:04:37 -05:00
Raul Jordan
bcbfa26fbd Merge branch 'develop' into feature/slasher 2021-03-30 15:58:18 -05:00
Raul Jordan
dd5b19f3de improve e2e resilience 2021-03-30 15:57:08 -05:00
Raul Jordan
c3084a2cfe merge e2e changes 2021-03-30 13:27:55 -05:00
Raul Jordan
c0e49a4217 Utilize Optimized Slasher for Remote Slashing Protection in Validator Client (#8674)
* begin removal of slasher client

* update mockgen

* removal of old slasher remote protector

* pass tests

* rename feature flag

* all tests pass

* deprecate the slasher grpc provider flags

* fix broken build

* time since
2021-03-29 16:35:25 -05:00
Raul Jordan
425816a2b4 compile 2021-03-26 18:59:18 -05:00
Raul Jordan
dd8e4edb41 better logging 2021-03-26 18:57:57 -05:00
Raul Jordan
7e3dae42c0 Optimize Slasher DB Operations (#8677)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-03-26 23:32:42 +00:00
Raul Jordan
d629297b80 fix feed items 2021-03-26 16:38:26 -05:00
Raul Jordan
abbc66e617 change simulator params 2021-03-26 09:49:54 -05:00
rauljordan
905f5c3c88 Merge branch 'feature/slasher' of github.com:prysmaticlabs/prysm into feature/slasher 2021-03-25 22:44:17 -05:00
rauljordan
980fab5439 detect slashable attestations tests moved to a better file 2021-03-25 22:44:09 -05:00
Ivan Martinez
a2b80eceb6 Add HighestAttestations function (#8654)
* Add HighestAttestations function

* Fix

* Fix

* Add benchmarks

* Change n

* Fix

* Remove N assignment

* Fix timer

* Change to encIndices

* skip deprecated slasher test

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-03-25 21:40:35 +00:00
Ivan Martinez
3c4b858c99 Mark old slasher client as deprecated (#8666)
* Mark all old slasher as deprecated

* Update slasher/node/node.go

* README

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-03-25 15:16:28 +00:00
Raul Jordan
082bb19c6d sim fix 2021-03-25 08:47:32 -05:00
Raul Jordan
10f6f06bb8 seconds per slot increase 2021-03-25 08:46:25 -05:00
Raul Jordan
dd31cfb929 increase seconds per slot 2021-03-25 08:46:01 -05:00
rauljordan
23cbd504ba reduce 2021-03-24 19:18:09 -05:00
Raul Jordan
be711a820e tidy 2021-03-24 17:59:04 -05:00
Raul Jordan
376f661f8a Merge branch 'develop' into feature/slasher 2021-03-24 17:58:49 -05:00
Raul Jordan
5cb12099e9 Process Found Slashings and Send to Operations Pool in Optimized Slasher (#8634)
* add in pool inserter

* integrate process slashings functions

* should return err

* add head state fetcher

* utilize head fetcher in process slashings

* builds but some tests fail

* simulator needs to be aware of genesis state

* rem testonly

* attestation tests passing

* attempt more test fixes

* all slasher tests passing, missing sim

* fix test

* add priv keys to simulator

* add pool

* valid sigs generated

* add valid signatures to attestations in simulator

* begin fixing simulator tests

* pass simulator tests

* gaz

* viz

* passing e2e

* slasher tests passing

* no lock

* pass

* build

* mock

* compile issues

* deep source
2021-03-24 22:51:11 +00:00
Raul Jordan
a430a4b8ae go sum 2021-03-24 15:33:55 -05:00
Raul Jordan
4526483392 Merge branch 'develop' into feature/slasher 2021-03-24 14:58:34 -05:00
Raul Jordan
0efb3ec54e resolve broken build 2021-03-24 14:35:25 -05:00
Raul Jordan
254cd6def0 merge develop 2021-03-24 14:26:45 -05:00
Raul Jordan
4943d635cd Test Actual Simulator Code in E2E, Remove Simulator Binary for Optimized Slasher (#8649)
* migrate simulator to test package

* sim test

* create slashing test

* res
2021-03-23 13:55:10 -05:00
Ivan Martinez
5184d63801 Add IsSlashableBlock and IsSlashableAttestation endpoints to beacon node (#8616)
* expose rpc slasher

* Imports

* Progress on endpoint

* Fix for commit, work on server integration

* refactor attestations

* genesis

* Undo gRPC changes

* Revert "Undo gRPC changes"

This reverts commit 4c0ac4c6c4.

* Cleanup

* Finish testing

* Fixes

* Plug slasher server into rpc

* more cleanups and correct placement of slasher service in node.go

* tests pass

* rpc annotate

* Add tests and mock

* Fix errors and duplicate

* Fix

* Add slasher check to service

* Fix

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-03-22 22:14:59 -05:00
Ivan Martinez
8d5c44ff77 Reorganize Slasher Detection (#8625)
* expose rpc slasher

* Imports

* Progress on endpoint

* Fix for commit, work on server integration

* refactor attestations

* Undo gRPC changes

* Fix conflict

* Remove IsSlashableBlock

* Fixes

* Clean up

* Fixes

* resolved genesis time test

* Fix logging

* Fixes

* Fixes

* Fix kafka

* Fix

* Fixes:wq
Gaz

* Fix test

* Fix suggestion

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-03-19 16:33:12 +00:00
Raul Jordan
8901cbc574 Verify Signatures of Detected Offenses in Optimized Slasher (#8626)
* smaller iface

* add validate funcs

* verify more slashings

* add verify sig and stategen

* more tests

* verification functions

* gaz

* broken test

* builds

* rename to att target state

* added sig verify test

* gaz
2021-03-19 08:40:58 -05:00
Raul Jordan
8fff0b6ca7 Integrate Optimized Slasher Into Beacon Node Runtime, Part 1 (#8602)
* initial runtime integration

* slasher integration

* revert

* revert

* use a genesis time fetcher

* define genesis time fetcher

* gaz

* use feature flag

* pass tests

* add in chain start notifier

* add enable slasher config value

* ensure slasher starts with the proper genesis time

* more input fix

* integrate slasher into blockchain and sync pipelines

* elim comment

* define right feeds

* fix some test builds

* fix sim

* goroutine for start func

* slasher genesis time

* pass in feeds to blockchain service

* change logs

* Update beacon-chain/sync/validate_beacon_attestation.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* add tests for logging

* add in tests for logging

* do not send block in blockchain service

* gaz

* fix build

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
2021-03-17 15:22:28 -05:00
Ivan Martinez
e7e62f5234 Add Slasher Simulator to E2E (#8604)
* Add simulator to e2e

* Fix E2E for simulator

* Add comment

* Fixes

* Add simulator logs to error logging
2021-03-16 02:43:19 +00:00
Raul Jordan
8f7c4cea4e Defer Attestations for Future Processing in Optimized Slasher (#8594)
* begin defer atts

* add in deferred processing logic

* all helper function tests passing

* remove irrelevant test

* fix typo

* remove unused metric

* Fix for terences comments

* Fixes

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
2021-03-15 20:03:45 -05:00
Raul Jordan
d7af14128e Add Slasher Simulator for Profiling, Benchmarking, and Testing (#8495)
* begin slasher simulator

* use slot ticker instead

* Begin on attestation generator

* Add block and att generator

* Fix tests

* Fix att generation

* Add test for generated indices

* Fix visibility

* Cleanup

* Add aggregation precent

* revert config

* revert

* pass tests

* imports

* commentary

* cmd

* Add logfile flag

* add better err handling

* add more detailed logging

* added more logging events

* gazelle

* merge and pass slasher tests

* move to cmd

* Add Ability for Slasher Simulator to Verify Slashings Are Detected (#8580)

* Collect slashings WIP

* Fix prob

* imports

* implement simulation check routine

* simulator overriding config working

* include the slashable att

* not catching slashings yet

* more fixes

* Change to e2e config and clean up logging

* Patch some more gaps

* imports

* detected prop slashings

* fully functional

* caught

* gaz

* sim

* Remove TODO

* Fix tests

* Fix gaz

* deepsource

* Deepsource

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* Fix build

* Fixes

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
2021-03-12 20:48:48 +00:00
Ivan Martinez
87bf2296a2 Add pruning functionality to slasher (#8591)
* Add pruning to slasher by historySize

* Add pruning to execution

* Plug in functionality

* Fix

* Add pruning to separate routine

* Fixes

* Fix tests
2021-03-12 04:43:50 +00:00
Raul Jordan
963d42567c Define Slasher gRPC Server and Endpoints (#8595)
* begin defining protos

* definition

* ethereumapis dep

* added in slasher pbs

* define implementations

* add in slasher

* edit vis
2021-03-11 13:36:41 -06:00
Ivan Martinez
daa575b87c Add slashing feeds to slasher (#8568)
* Add feeds for slashings

* Add slashing feedss

* Fix

* fix imports

* Update beacon-chain/slasher/detect_blocks.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
2021-03-08 10:52:59 -06:00
Raul Jordan
346629b205 Snappy Compress Slasher Chunks (#8561)
* work towards compression

* slasher chunks compressed

* fix params test

* go deep source

* chunk keys test

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-03-05 18:52:36 +00:00
Ivan Martinez
f5f97c3d1f Prepare slasher to construct full slashing proof (#8551)
* Prepare slasher to construct full slashing proof

* Fix comments

* Fix tests

* Fix tests

* Fix tests
2021-03-05 10:13:59 -06:00
Raul Jordan
5259a4b698 Metrics for Optimized Slasher (#8560)
* add metrics

* track metrics

* gaz

* add in all slasher metrics

* remove bad metric
2021-03-05 02:23:26 +00:00
Raul Jordan
746315815e go mod tidy 2021-03-04 16:48:46 -06:00
Raul Jordan
5678fbe591 Merge branch 'develop' into feature/slasher 2021-03-04 16:41:20 -06:00
Raul Jordan
a82fc98453 Better Error Messages in Optimized Slasher (#8553)
* better annotated errors

* handle last err

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2021-03-04 20:32:21 +00:00
Raul Jordan
30fec47d57 Merge branch 'develop' into feature/slasher 2021-03-04 11:34:42 -06:00
Raul Jordan
fd33c70a5c Fallback to DB When Retrieving Missing Chunk in Optimized Slasher (#8548)
* begin more comprehensive tests across epoch boundaries

* add in lock

* integrate changes from Ivan's PR

* minimal reproduction

* fix chunk index issue

* passing tests

* gaz

* naming
2021-03-03 15:44:40 -06:00
Ivan Martinez
ec678939a8 Store full IndexedAttestation and SignedBeaconBlockHeader for slasher (#8536)
* Change DB and slasher to handle full attestation/block header objects

* Undo proto

* Add comments

* work on tests

* Fix tests

* Fixes

* Testing fixes

* Fix tests

* Fix again

* add helper

* Fix build

* Fixes

* Fixes

* Fixes

* Comment fixes

* More comments

* fix
2021-03-03 11:30:48 -06:00
Raul Jordan
9553b82ed3 Merge branch 'develop' into feature/slasher 2021-03-01 20:18:48 -06:00
Raul Jordan
0bb61cf3fe Merge branch 'develop' into feature/slasher 2021-02-22 11:37:47 -06:00
Raul Jordan
f7cc07c750 Merge branch 'develop' into feature/slasher 2021-02-22 11:24:20 -06:00
Raul Jordan
c56d09dff3 Attester Double Vote Detection for Optimized Slasher (#8480)
* update routine added

* test build fix

* begin adding integration test

* proper logging of slashing events

* commentary and examples for next start epoch interface methods

* include comprehensive comments for new iface methods

* better comments

* integration tests for surrounding, surrounded, and not slashable

* test for logging helper

* tests for the next start epoch methods

* typo

* add in methods and tests

* add start epoch tests

* tests for new methods added

* tests pass

* passing test

* imports spacing

* add all required logic to check for double vote

* check double vote logic

* amend db func

* check on disk

* more efficient db method

* tests passing

* check respect to each other

* add tests for double vote detection

* gaz

* tests passed

* fix passthrough build

* double gaz

* add in spans

* faster concat

* gaz
2021-02-22 11:13:55 -06:00
Raul Jordan
8cdbcd9700 Double Block Slashing Detection for Optimized Slasher (#8470)
* add double block detect

* db tests'

* kafka deepsource

* imports

* comment

* address all Radek's comments

* add comment

* comment to check double proposals on disk

* fix kafka passthrough.go build

* pass tests

* comment

* build

* deep source

* imports

* imports
2021-02-22 09:50:19 -06:00
Radosław Kapka
19ae9b5590 Remove mutated fields from slasher args (#8487) 2021-02-22 08:45:20 -06:00
Raul Jordan
2913947c24 Detect Slashable Surround Votes in Optimized Slasher (#8446)
* update routine added

* test build fix

* begin adding integration test

* proper logging of slashing events

* commentary and examples for next start epoch interface methods

* include comprehensive comments for new iface methods

* better comments

* integration tests for surrounding, surrounded, and not slashable

* test for logging helper

* tests for the next start epoch methods

* typo

* add in methods and tests

* add start epoch tests

* tests for new methods added

* tests pass

* passing test

* imports spacing

* tests passing

* db test passing

* radek comments

* deep source

* added more test cases

* further simplify

* passthrough

* comment on struct

* commentary on skipping validator chunk index

* map capacity
2021-02-19 09:53:29 -06:00
Raul Jordan
c342d35bbf Begin Receiving and Processing Blocks for Optimized Slasher (#8450)
* add in receive blocks logic

* use different locks

* add unit test for block receiver functions

* fix types

* build fix

* terence feedback

* fix broken build
2021-02-17 13:15:25 -06:00
Raul Jordan
b285722f5c fix e2e build 2021-02-17 11:44:58 -06:00
Raul Jordan
16c6ea9489 fix build issues when merging with develop 2021-02-17 11:35:08 -06:00
Raul Jordan
72bfb94e53 merge develop 2021-02-17 10:56:55 -06:00
Raul Jordan
976297725a deps fix 2021-02-15 23:38:34 -06:00
Raul Jordan
9b6f93184d Merge branch 'develop' into feature/slasher 2021-02-15 23:35:40 -06:00
Raul Jordan
a6fde55646 Methods For StartEpoch and Slashing Helper Types for Optimized Slasher (#8442)
* add in methods and tests

* add start epoch tests

* tests for new methods added

* tests pass

* Update beacon-chain/slasher/chunks.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Update beacon-chain/slasher/chunks.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* right order of operations

* fix order

* order

* tests

* comment

* even more simplification

* comments

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2021-02-12 16:18:04 -06:00
Raul Jordan
a48de9ab69 Detection Algorithm for Optimized Slasher (#8423)
* detect

* more separation of concerns

* leverage the chunk kind type to create the same functionality easily

* builds

* begin writing tests

* add even more tests to our logic

* using fewer input args via opts struct

* all comments done for new functions

* fix build

* improvement to helpers

* determine chunk indices to load, then fetch all in batch

* batch load chunks

* add test for determine chunks for update

* all tests pass

* gaz

* fix kafka passthrough build

* deep source
2021-02-10 13:19:53 -06:00
rauljordan
429c94534e simplify and cleanup 2021-02-09 21:47:58 -06:00
rauljordan
12defb914d passthrough fix 2021-02-05 14:14:36 -06:00
Raul Jordan
ce9cf8cf1f Merge branch 'develop' into feature/slasher 2021-02-05 14:11:58 -06:00
Raul Jordan
5596f8b0d4 Detection Further Helpers and Types for Attester Slashing Detection (#8400)
* compact rename

* rename

* imports

* add import

* tests
2021-02-05 11:11:25 -06:00
Raul Jordan
2864d5f070 Add Helpers Required for Attestation Slashing Detection, Begin Detection Framework (#8386)
* include detection functions

* begin detection helpers such as batching and grouping indexed attestations

* add more tests to the detection process

* tests done for detection helpers

* add proper todo format

* test

* terence comments

* better queue safety with lock

* with fields for logrus
2021-02-03 14:33:05 -06:00
Raul Jordan
38d681341c Merge branch 'develop' into feature/slasher 2021-02-02 16:54:42 -06:00
Radosław Kapka
90f2ef801a Remove redundant bool return value from CheckSlashable (#8375) 2021-02-01 16:12:00 +00:00
Raul Jordan
d9bbbe5a4e Implement MaxSpanChunksSlice for Optimized Slasher (#8358)
* add in max spans logic

* tests for check slashable max

* max span chunks complete

* named params

* better comment
2021-01-29 11:05:05 -06:00
Raul Jordan
24dde8fb82 merge 2021-01-28 19:42:53 -06:00
Raul Jordan
b6b5bb0c51 Merge branch 'develop' into feature/slasher 2021-01-28 19:42:23 -06:00
Raul Jordan
971a15f907 Defining and Implementing the Chunker Interface for MinSpans (#8350)
* chunker methods and comments

* more chunker tests

* add more chunk tests

* tests passing, now missing update test

* better comment

* gaz

* better annotations

* test for updating a single chunk

* multiple chunks test

* fix test to use deepequal

* chunks tests now properly passing

* deep source fixes

* better annotation for epoch staggering

* victor comments
2021-01-28 14:21:13 -06:00
Raul Jordan
3e2c6a9522 Add Database Schema and Methods for Optimized Slasher (#8342)
* begin adding db schema

* define required schema

* add eth2 types

* use custom types helpers

* begin tests for schema

* update deps

* edit workspace

* gaz

* passthrough

* gaz

* terence feedback
2021-01-27 15:38:03 -06:00
Raul Jordan
939a36df58 Begin Slasher Service Definition and Configuration (#8335)
* begin defining the service itself

* tests for receive atts

* begin defining necessary config helpers

* thorough comments

* more tests

* 100% coverage and docs

* gazelle

* terence feedback

* types

* rename

* fix build
2021-01-26 13:00:49 -06:00
Raul Jordan
de89d816ad begin slasher package 2021-01-25 16:03:44 -06:00
74 changed files with 1160 additions and 932 deletions

View File

@@ -27,6 +27,7 @@ go_library(
],
deps = [
"//async:go_default_library",
"//async/event:go_default_library",
"//beacon-chain/cache:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core:go_default_library",

View File

@@ -16,6 +16,7 @@ import (
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/crypto/bls"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
ethpbv1 "github.com/prysmaticlabs/prysm/proto/eth/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
@@ -106,6 +107,33 @@ func (s *Service) onBlock(ctx context.Context, signed block.SignedBeaconBlock, b
return err
}
// If slasher is configured, forward the attestations in the block via
// an event feed for processing.
if features.Get().EnableSlasher {
// Feed the indexed attestation to slasher if enabled. This action
// is done in the background to avoid adding more load to this critical code path.
go func() {
// Using a different context to prevent timeouts as this operation can be expensive
// and we want to avoid affecting the critical code path.
ctx := context.TODO()
for _, att := range signed.Block().Body().Attestations() {
committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
log.WithError(err).Error("Could not get attestation committee")
tracing.AnnotateError(span, err)
return
}
indexedAtt, err := attestation.ConvertToIndexed(ctx, att, committee)
if err != nil {
log.WithError(err).Error("Could not convert to indexed attestation")
tracing.AnnotateError(span, err)
return
}
s.cfg.SlasherAttestationsFeed.Send(indexedAtt)
}
}()
}
// Update justified check point.
currJustifiedEpoch := s.justifiedCheckpt.Epoch
if postState.CurrentJustifiedCheckpoint().Epoch > currJustifiedEpoch {

View File

@@ -11,6 +11,7 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
@@ -82,6 +83,7 @@ type Config struct {
ForkChoiceStore f.ForkChoicer
AttService *attestations.Service
StateGen *stategen.State
SlasherAttestationsFeed *event.Feed
WeakSubjectivityCheckpt *ethpb.Checkpoint
}

View File

@@ -7,12 +7,11 @@ go_library(
visibility = [
"//beacon-chain:__subpackages__",
"//contracts/deposit:__pkg__",
"//crypto/keystore:__pkg__",
"//fuzz:__pkg__",
"//network/forks:__pkg__",
"//proto/prysm/v1alpha1/attestation:__pkg__",
"//runtime/interop:__pkg__",
"//shared/attestationutil:__pkg__",
"//shared/keystore:__pkg__",
"//slasher:__subpackages__",
"//testing/altair:__pkg__",
"//testing/benchmark/benchmark_files:__subpackages__",

View File

@@ -18,12 +18,12 @@ go_library(
visibility = [
"//beacon-chain:__subpackages__",
"//contracts/deposit:__pkg__",
"//crypto/keystore:__pkg__",
"//fuzz:__pkg__",
"//network/forks:__pkg__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/prysm/v1alpha1/attestation:__pkg__",
"//runtime/interop:__pkg__",
"//shared/attestationutil:__pkg__",
"//shared/keystore:__pkg__",
"//slasher:__subpackages__",
"//testing/altair:__pkg__",
"//testing/benchmark/benchmark_files:__subpackages__",

View File

@@ -21,6 +21,7 @@ go_library(
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/db/kv:go_default_library",
"//beacon-chain/db/slasherkv:go_default_library",
"//beacon-chain/forkchoice:go_default_library",
"//beacon-chain/forkchoice/protoarray:go_default_library",
"//beacon-chain/gateway:go_default_library",
@@ -34,6 +35,7 @@ go_library(
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/rpc:go_default_library",
"//beacon-chain/rpc/apimiddleware:go_default_library",
"//beacon-chain/slasher:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//beacon-chain/sync/initial-sync:go_default_library",

View File

@@ -24,6 +24,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/db/kv"
"github.com/prysmaticlabs/prysm/beacon-chain/db/slasherkv"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
"github.com/prysmaticlabs/prysm/beacon-chain/gateway"
@@ -37,6 +38,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/beacon-chain/slasher"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
regularsync "github.com/prysmaticlabs/prysm/beacon-chain/sync"
initialsync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync"
@@ -64,24 +66,27 @@ const debugGrpcMaxMsgSize = 1 << 27
// full PoS node. It handles the lifecycle of the entire system and registers
// services to a service registry.
type BeaconNode struct {
cliCtx *cli.Context
ctx context.Context
cancel context.CancelFunc
services *runtime.ServiceRegistry
lock sync.RWMutex
stop chan struct{} // Channel to wait for termination notifications.
db db.Database
attestationPool attestations.Pool
exitPool voluntaryexits.PoolManager
slashingsPool slashings.PoolManager
syncCommitteePool synccommittee.Pool
depositCache *depositcache.DepositCache
stateFeed *event.Feed
blockFeed *event.Feed
opFeed *event.Feed
forkChoiceStore forkchoice.ForkChoicer
stateGen *stategen.State
collector *bcnodeCollector
cliCtx *cli.Context
ctx context.Context
cancel context.CancelFunc
services *runtime.ServiceRegistry
lock sync.RWMutex
stop chan struct{} // Channel to wait for termination notifications.
db db.Database
slasherDB db.SlasherDatabase
attestationPool attestations.Pool
exitPool voluntaryexits.PoolManager
slashingsPool slashings.PoolManager
syncCommitteePool synccommittee.Pool
depositCache *depositcache.DepositCache
stateFeed *event.Feed
blockFeed *event.Feed
opFeed *event.Feed
forkChoiceStore forkchoice.ForkChoicer
stateGen *stategen.State
collector *bcnodeCollector
slasherBlockHeadersFeed *event.Feed
slasherAttestationsFeed *event.Feed
}
// New creates a new node instance, sets up configuration options, and registers
@@ -108,18 +113,20 @@ func New(cliCtx *cli.Context) (*BeaconNode, error) {
ctx, cancel := context.WithCancel(cliCtx.Context)
beacon := &BeaconNode{
cliCtx: cliCtx,
ctx: ctx,
cancel: cancel,
services: registry,
stop: make(chan struct{}),
stateFeed: new(event.Feed),
blockFeed: new(event.Feed),
opFeed: new(event.Feed),
attestationPool: attestations.NewPool(),
exitPool: voluntaryexits.NewPool(),
slashingsPool: slashings.NewPool(),
syncCommitteePool: synccommittee.NewPool(),
cliCtx: cliCtx,
ctx: ctx,
cancel: cancel,
services: registry,
stop: make(chan struct{}),
stateFeed: new(event.Feed),
blockFeed: new(event.Feed),
opFeed: new(event.Feed),
attestationPool: attestations.NewPool(),
exitPool: voluntaryexits.NewPool(),
slashingsPool: slashings.NewPool(),
syncCommitteePool: synccommittee.NewPool(),
slasherBlockHeadersFeed: new(event.Feed),
slasherAttestationsFeed: new(event.Feed),
}
depositAddress, err := registration.DepositContractAddress()
@@ -130,6 +137,10 @@ func New(cliCtx *cli.Context) (*BeaconNode, error) {
return nil, err
}
if err := beacon.startSlasherDB(cliCtx); err != nil {
return nil, err
}
beacon.startStateGen()
if err := beacon.registerP2P(cliCtx); err != nil {
@@ -162,6 +173,10 @@ func New(cliCtx *cli.Context) (*BeaconNode, error) {
return nil, err
}
if err := beacon.registerSlasherService(); err != nil {
return nil, err
}
if err := beacon.registerRPCService(); err != nil {
return nil, err
}
@@ -329,11 +344,9 @@ func (b *BeaconNode) startDB(cliCtx *cli.Context, depositAddress string) error {
return errors.Wrap(err, "could not load genesis from file")
}
}
if err := b.db.EnsureEmbeddedGenesis(b.ctx); err != nil {
return err
}
knownContract, err := b.db.DepositContractAddress(b.ctx)
if err != nil {
return err
@@ -351,7 +364,53 @@ func (b *BeaconNode) startDB(cliCtx *cli.Context, depositAddress string) error {
knownContract, addr.Bytes())
}
log.Infof("Deposit contract: %#x", addr.Bytes())
return nil
}
func (b *BeaconNode) startSlasherDB(cliCtx *cli.Context) error {
if !features.Get().EnableSlasher {
return nil
}
baseDir := cliCtx.String(cmd.DataDirFlag.Name)
dbPath := filepath.Join(baseDir, kv.BeaconNodeDbDirName)
clearDB := cliCtx.Bool(cmd.ClearDB.Name)
forceClearDB := cliCtx.Bool(cmd.ForceClearDB.Name)
log.WithField("database-path", dbPath).Info("Checking DB")
d, err := slasherkv.NewKVStore(b.ctx, dbPath, &slasherkv.Config{
InitialMMapSize: cliCtx.Int(cmd.BoltMMapInitialSizeFlag.Name),
})
if err != nil {
return err
}
clearDBConfirmed := false
if clearDB && !forceClearDB {
actionText := "This will delete your beacon chain database stored in your data directory. " +
"Your database backups will not be removed - do you want to proceed? (Y/N)"
deniedText := "Database will not be deleted. No changes have been made."
clearDBConfirmed, err = cmd.ConfirmAction(actionText, deniedText)
if err != nil {
return err
}
}
if clearDBConfirmed || forceClearDB {
log.Warning("Removing database")
if err := d.Close(); err != nil {
return errors.Wrap(err, "could not close db prior to clearing")
}
if err := d.ClearDB(); err != nil {
return errors.Wrap(err, "could not clear database")
}
d, err = slasherkv.NewKVStore(b.ctx, dbPath, &slasherkv.Config{
InitialMMapSize: cliCtx.Int(cmd.BoltMMapInitialSizeFlag.Name),
})
if err != nil {
return errors.Wrap(err, "could not create new database")
}
}
b.slasherDB = d
return nil
}
@@ -441,6 +500,7 @@ func (b *BeaconNode) registerBlockchainService() error {
ForkChoiceStore: b.forkChoiceStore,
AttService: attService,
StateGen: b.stateGen,
SlasherAttestationsFeed: b.slasherAttestationsFeed,
WeakSubjectivityCheckpt: wsCheckpt,
})
if err != nil {
@@ -500,18 +560,21 @@ func (b *BeaconNode) registerSyncService() error {
}
rs := regularsync.NewService(b.ctx, &regularsync.Config{
DB: b.db,
P2P: b.fetchP2P(),
Chain: chainService,
InitialSync: initSync,
StateNotifier: b,
BlockNotifier: b,
OperationNotifier: b,
AttPool: b.attestationPool,
ExitPool: b.exitPool,
SlashingPool: b.slashingsPool,
SyncCommsPool: b.syncCommitteePool,
StateGen: b.stateGen,
DB: b.db,
P2P: b.fetchP2P(),
Chain: chainService,
InitialSync: initSync,
StateNotifier: b,
BlockNotifier: b,
AttestationNotifier: b,
OperationNotifier: b,
AttPool: b.attestationPool,
ExitPool: b.exitPool,
SlashingPool: b.slashingsPool,
SyncCommsPool: b.syncCommitteePool,
StateGen: b.stateGen,
SlasherAttestationsFeed: b.slasherAttestationsFeed,
SlasherBlockHeadersFeed: b.slasherBlockHeadersFeed,
})
return b.services.RegisterService(rs)
@@ -533,6 +596,36 @@ func (b *BeaconNode) registerInitialSyncService() error {
return b.services.RegisterService(is)
}
func (b *BeaconNode) registerSlasherService() error {
if !features.Get().EnableSlasher {
return nil
}
var chainService *blockchain.Service
if err := b.services.FetchService(&chainService); err != nil {
return err
}
var syncService *initialsync.Service
if err := b.services.FetchService(&syncService); err != nil {
return err
}
slasherSrv, err := slasher.New(b.ctx, &slasher.ServiceConfig{
IndexedAttestationsFeed: b.slasherAttestationsFeed,
BeaconBlockHeadersFeed: b.slasherBlockHeadersFeed,
Database: b.slasherDB,
StateNotifier: b,
AttestationStateFetcher: chainService,
StateGen: b.stateGen,
SlashingPoolInserter: b.slashingsPool,
SyncChecker: syncService,
HeadStateFetcher: chainService,
})
if err != nil {
return err
}
return b.services.RegisterService(slasherSrv)
}
func (b *BeaconNode) registerRPCService() error {
var chainService *blockchain.Service
if err := b.services.FetchService(&chainService); err != nil {
@@ -549,6 +642,13 @@ func (b *BeaconNode) registerRPCService() error {
return err
}
var slasherService *slasher.Service
if features.Get().EnableSlasher {
if err := b.services.FetchService(&slasherService); err != nil {
return err
}
}
genesisValidators := b.cliCtx.Uint64(flags.InteropNumValidatorsFlag.Name)
genesisStatePath := b.cliCtx.String(flags.InteropGenesisStateFlag.Name)
var depositFetcher depositcache.DepositFetcher
@@ -604,6 +704,7 @@ func (b *BeaconNode) registerRPCService() error {
AttestationsPool: b.attestationPool,
ExitPool: b.exitPool,
SlashingsPool: b.slashingsPool,
SlashingChecker: slasherService,
SyncCommitteeObjectPool: b.syncCommitteePool,
POWChainService: web3Service,
ChainStartFetcher: chainStartFetcher,

View File

@@ -51,6 +51,10 @@ var refreshRate = slots.DivideSlotBy(2)
// maxBadResponses is the maximum number of bad responses from a peer before we stop talking to it.
const maxBadResponses = 5
// pubsubQueueSize is the size that we assign to our validation queue and outbound message queue for
// gossipsub.
const pubsubQueueSize = 600
// maxDialTimeout is the timeout for a single peer dial.
var maxDialTimeout = params.BeaconNetworkConfig().RespTimeout
@@ -141,8 +145,8 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) {
return MsgID(s.genesisValidatorsRoot, pmsg)
}),
pubsub.WithSubscriptionFilter(s),
pubsub.WithPeerOutboundQueueSize(256),
pubsub.WithValidateQueueSize(256),
pubsub.WithPeerOutboundQueueSize(pubsubQueueSize),
pubsub.WithValidateQueueSize(pubsubQueueSize),
pubsub.WithPeerScore(peerScoringParams()),
pubsub.WithPeerScoreInspect(s.peerInspector, time.Minute),
pubsub.WithGossipSubParams(pubsubGossipParam()),

View File

@@ -76,6 +76,7 @@ go_test(
deps = [
"//async/event:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core:go_default_library",
"//beacon-chain/core/feed:go_default_library",
"//beacon-chain/core/feed/state:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
@@ -84,6 +85,7 @@ go_test(
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/powchain/testing:go_default_library",
"//beacon-chain/powchain/types:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//config/params:go_default_library",
"//container/trie:go_default_library",
"//contracts/deposit:go_default_library",
@@ -93,6 +95,7 @@ go_test(
"//network:go_default_library",
"//network/authorization:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",

View File

@@ -616,6 +616,16 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*protodb.Deposit
}
// Set deposit index to the one in the current archived state.
currIndex = fState.Eth1DepositIndex()
// when a node pauses for some time and starts again, the deposits to finalize
// accumulates. we finalize them here before we are ready to receive a block.
// Otherwise, the first few blocks will be slower to compute as we will
// hold the lock and be busy finalizing the deposits.
s.cfg.DepositCache.InsertFinalizedDeposits(ctx, int64(currIndex))
// Deposit proofs are only used during state transition and can be safely removed to save space.
if err = s.cfg.DepositCache.PruneProofs(ctx, int64(currIndex)); err != nil {
return errors.Wrap(err, "could not prune deposit proofs")
}
}
validDepositsCount.Add(float64(currIndex))
// Only add pending deposits if the container slice length

View File

@@ -17,14 +17,18 @@ import (
gethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
dbutil "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
mockPOW "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/config/params"
contracts "github.com/prysmaticlabs/prysm/contracts/deposit"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/clientstats"
"github.com/prysmaticlabs/prysm/network"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
protodb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
@@ -463,6 +467,82 @@ func TestInitDepositCache_OK(t *testing.T) {
require.Equal(t, 3, len(s.cfg.DepositCache.PendingContainers(context.Background(), nil)))
}
func TestInitDepositCacheWithFinalization_OK(t *testing.T) {
ctrs := []*protodb.DepositContainer{
{
Index: 0,
Eth1BlockHeight: 2,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: bytesutil.PadTo([]byte{0}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Index: 1,
Eth1BlockHeight: 4,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: bytesutil.PadTo([]byte{1}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
{
Index: 2,
Eth1BlockHeight: 6,
Deposit: &ethpb.Deposit{
Data: &ethpb.Deposit_Data{
PublicKey: bytesutil.PadTo([]byte{2}, 48),
WithdrawalCredentials: make([]byte, 32),
Signature: make([]byte, 96),
},
},
},
}
gs, _ := util.DeterministicGenesisState(t, 1)
beaconDB := dbutil.SetupDB(t)
s := &Service{
chainStartData: &protodb.ChainStartData{Chainstarted: false},
preGenesisState: gs,
cfg: &Web3ServiceConfig{BeaconDB: beaconDB},
}
var err error
s.cfg.DepositCache, err = depositcache.New()
require.NoError(t, err)
require.NoError(t, s.initDepositCaches(context.Background(), ctrs))
require.Equal(t, 0, len(s.cfg.DepositCache.PendingContainers(context.Background(), nil)))
headBlock := util.NewBeaconBlock()
headRoot, err := headBlock.Block.HashTreeRoot()
require.NoError(t, err)
stateGen := stategen.New(beaconDB)
emptyState, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, s.cfg.BeaconDB.SaveGenesisBlockRoot(context.Background(), headRoot))
require.NoError(t, s.cfg.BeaconDB.SaveState(context.Background(), emptyState, headRoot))
require.NoError(t, stateGen.SaveState(context.Background(), headRoot, emptyState))
s.cfg.StateGen = stateGen
require.NoError(t, emptyState.SetEth1DepositIndex(2))
ctx := context.Background()
require.NoError(t, stateGen.SaveState(ctx, headRoot, emptyState))
require.NoError(t, beaconDB.SaveState(ctx, emptyState, headRoot))
require.NoError(t, beaconDB.SaveBlock(ctx, wrapper.WrappedPhase0SignedBeaconBlock(headBlock)))
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, &ethpb.Checkpoint{Epoch: core.SlotToEpoch(0), Root: headRoot[:]}))
s.chainStartData.Chainstarted = true
require.NoError(t, s.initDepositCaches(context.Background(), ctrs))
deps := s.cfg.DepositCache.NonFinalizedDeposits(context.Background(), nil)
assert.Equal(t, 0, len(deps))
}
func TestNewService_EarliestVotingBlock(t *testing.T) {
testAcc, err := contracts.Setup()
require.NoError(t, err, "Unable to set up simulated backend")

View File

@@ -30,8 +30,10 @@ go_library(
"//beacon-chain/rpc/prysm/v1alpha1/beacon:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/debug:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/node:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/slasher:go_default_library",
"//beacon-chain/rpc/prysm/v1alpha1/validator:go_default_library",
"//beacon-chain/rpc/statefetcher:go_default_library",
"//beacon-chain/slasher:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync:go_default_library",
"//config/features:go_default_library",

View File

@@ -0,0 +1,29 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"attestations.go",
"blocks.go",
"server.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/slasher",
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/slasher:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["server_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/slasher:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/require:go_default_library",
],
)

View File

@@ -0,0 +1,34 @@
package slasher
import (
"context"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// IsSlashableAttestation returns an attester slashing if an input
// attestation is found to be slashable.
func (s *Server) IsSlashableAttestation(
ctx context.Context, req *ethpb.IndexedAttestation,
) (*ethpb.AttesterSlashingResponse, error) {
attesterSlashings, err := s.SlashingChecker.IsSlashableAttestation(ctx, req)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine if attestation is slashable: %v", err)
}
if len(attesterSlashings) > 0 {
return &ethpb.AttesterSlashingResponse{
AttesterSlashings: attesterSlashings,
}, nil
}
return &ethpb.AttesterSlashingResponse{}, nil
}
// HighestAttestations returns the highest source and target epochs attested for
// validator indices that have been observed by slasher.
func (_ *Server) HighestAttestations(
ctx context.Context, req *ethpb.HighestAttestationRequest,
) (*ethpb.HighestAttestationResponse, error) {
return nil, status.Error(codes.Unimplemented, "Unimplemented")
}

View File

@@ -0,0 +1,28 @@
package slasher
import (
"context"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// IsSlashableBlock returns a proposer slashing if an input
// signed beacon block header is found to be slashable.
func (s *Server) IsSlashableBlock(
ctx context.Context, req *ethpb.SignedBeaconBlockHeader,
) (*ethpb.ProposerSlashingResponse, error) {
proposerSlashing, err := s.SlashingChecker.IsSlashableBlock(ctx, req)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not determine if block is slashable: %v", err)
}
if proposerSlashing == nil {
return &ethpb.ProposerSlashingResponse{
ProposerSlashings: []*ethpb.ProposerSlashing{},
}, nil
}
return &ethpb.ProposerSlashingResponse{
ProposerSlashings: []*ethpb.ProposerSlashing{proposerSlashing},
}, nil
}

View File

@@ -0,0 +1,12 @@
// Package slasher defines a gRPC server implementation of a slasher service
// which allows for checking if attestations or blocks are slashable.
package slasher
import (
slasherservice "github.com/prysmaticlabs/prysm/beacon-chain/slasher"
)
// Server defines a server implementation of the gRPC slasher service.
type Server struct {
SlashingChecker slasherservice.SlashingChecker
}

View File

@@ -0,0 +1,54 @@
package slasher
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/slasher"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestServer_IsSlashableAttestation_SlashingFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
AttesterSlashingFound: true,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableAttestation(ctx, &ethpb.IndexedAttestation{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.AttesterSlashings) > 0)
}
func TestServer_IsSlashableAttestation_SlashingNotFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
AttesterSlashingFound: false,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableAttestation(ctx, &ethpb.IndexedAttestation{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.AttesterSlashings) == 0)
}
func TestServer_IsSlashableBlock_SlashingFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
ProposerSlashingFound: true,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableBlock(ctx, &ethpb.SignedBeaconBlockHeader{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.ProposerSlashings) > 0)
}
func TestServer_IsSlashableBlock_SlashingNotFound(t *testing.T) {
mockSlasher := &slasher.MockSlashingChecker{
ProposerSlashingFound: false,
}
s := Server{SlashingChecker: mockSlasher}
ctx := context.Background()
slashing, err := s.IsSlashableBlock(ctx, &ethpb.SignedBeaconBlockHeader{})
require.NoError(t, err)
require.Equal(t, true, len(slashing.ProposerSlashings) == 0)
}

View File

@@ -34,8 +34,10 @@ import (
beaconv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/beacon"
debugv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/debug"
nodev1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/node"
slasherv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/slasher"
validatorv1alpha1 "github.com/prysmaticlabs/prysm/beacon-chain/rpc/prysm/v1alpha1/validator"
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/statefetcher"
slasherservice "github.com/prysmaticlabs/prysm/beacon-chain/slasher"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
chainSync "github.com/prysmaticlabs/prysm/beacon-chain/sync"
"github.com/prysmaticlabs/prysm/config/features"
@@ -93,6 +95,7 @@ type Config struct {
AttestationsPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingsPool slashings.PoolManager
SlashingChecker slasherservice.SlashingChecker
SyncCommitteeObjectPool synccommittee.Pool
SyncService chainSync.Checker
Broadcaster p2p.Broadcaster
@@ -234,6 +237,10 @@ func (s *Service) Start() {
HeadFetcher: s.cfg.HeadFetcher,
}
slasherServer := &slasherv1alpha1.Server{
SlashingChecker: s.cfg.SlashingChecker,
}
beaconChainServer := &beaconv1alpha1.Server{
Ctx: s.ctx,
BeaconDB: s.cfg.BeaconDB,
@@ -280,6 +287,7 @@ func (s *Service) Start() {
ethpbv1alpha1.RegisterNodeServer(s.grpcServer, nodeServer)
ethpbservice.RegisterBeaconNodeServer(s.grpcServer, nodeServerV1)
ethpbv1alpha1.RegisterHealthServer(s.grpcServer, nodeServer)
ethpbv1alpha1.RegisterSlasherServer(s.grpcServer, slasherServer)
ethpbv1alpha1.RegisterBeaconChainServer(s.grpcServer, beaconChainServer)
ethpbservice.RegisterBeaconChainServer(s.grpcServer, beaconChainServerV1)
ethpbservice.RegisterEventsServer(s.grpcServer, &events.Server{

View File

@@ -10,10 +10,12 @@ go_library(
"helpers.go",
"log.go",
"metrics.go",
"mock_slashing_checker.go",
"params.go",
"process_slashings.go",
"queue.go",
"receive.go",
"rpc.go",
"service.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/slasher",
@@ -46,6 +48,8 @@ go_library(
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//trace:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
],
)
@@ -60,17 +64,22 @@ go_test(
"process_slashings_test.go",
"queue_test.go",
"receive_test.go",
"rpc_test.go",
"service_test.go",
],
embed = [":go_default_library"],
deps = [
"//async/event:go_default_library",
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/core:go_default_library",
"//beacon-chain/core/feed:go_default_library",
"//beacon-chain/core/feed/state:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/db/testing:go_default_library",
"//beacon-chain/operations/slashings:go_default_library",
"//beacon-chain/slasher/types:go_default_library",
"//beacon-chain/state/stategen:go_default_library",
"//beacon-chain/sync/initial-sync/testing:go_default_library",
"//config/params:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
@@ -78,8 +87,10 @@ go_test(
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"//time/slots:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)

View File

@@ -147,3 +147,24 @@ func Test_processQueuedBlocks_NotSlashable(t *testing.T) {
<-exitChan
require.LogsDoNotContain(t, hook, "Proposer slashing detected")
}
func createProposalWrapper(t *testing.T, slot types.Slot, proposerIndex types.ValidatorIndex, signingRoot []byte) *slashertypes.SignedBlockHeaderWrapper {
header := &ethpb.BeaconBlockHeader{
Slot: slot,
ProposerIndex: proposerIndex,
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: bytesutil.PadTo(signingRoot, 32),
BodyRoot: params.BeaconConfig().ZeroHash[:],
}
signRoot, err := header.HashTreeRoot()
require.NoError(t, err)
fakeSig := make([]byte, 96)
copy(fakeSig, "hello")
return &slashertypes.SignedBlockHeaderWrapper{
SignedBeaconBlockHeader: &ethpb.SignedBeaconBlockHeader{
Header: header,
Signature: fakeSig,
},
SigningRoot: signRoot,
}
}

View File

@@ -0,0 +1,57 @@
package slasher
import (
"context"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
type MockSlashingChecker struct {
AttesterSlashingFound bool
ProposerSlashingFound bool
}
func (s *MockSlashingChecker) IsSlashableBlock(ctx context.Context, proposal *ethpb.SignedBeaconBlockHeader) (*ethpb.ProposerSlashing, error) {
if s.ProposerSlashingFound {
return &ethpb.ProposerSlashing{
Header_1: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 0,
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: params.BeaconConfig().ZeroHash[:],
},
Signature: params.BeaconConfig().EmptySignature[:],
},
Header_2: &ethpb.SignedBeaconBlockHeader{
Header: &ethpb.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 0,
ParentRoot: params.BeaconConfig().ZeroHash[:],
StateRoot: params.BeaconConfig().ZeroHash[:],
BodyRoot: params.BeaconConfig().ZeroHash[:],
},
Signature: params.BeaconConfig().EmptySignature[:],
},
}, nil
}
return nil, nil
}
func (s *MockSlashingChecker) IsSlashableAttestation(ctx context.Context, attestation *ethpb.IndexedAttestation) ([]*ethpb.AttesterSlashing, error) {
if s.AttesterSlashingFound {
return []*ethpb.AttesterSlashing{
{
Attestation_1: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{},
},
Attestation_2: &ethpb.IndexedAttestation{
Data: &ethpb.AttestationData{},
},
},
}, nil
}
return nil, nil
}

View File

@@ -308,26 +308,3 @@ func TestService_processQueuedBlocks(t *testing.T) {
<-exitChan
assert.LogsContain(t, hook, "New slot, processing queued")
}
func createProposalWrapper(t *testing.T, slot types.Slot, proposerIndex types.ValidatorIndex, signingRoot []byte) *slashertypes.SignedBlockHeaderWrapper {
header := &ethpb.BeaconBlockHeader{
Slot: slot,
ProposerIndex: proposerIndex,
ParentRoot: params2.BeaconConfig().ZeroHash[:],
StateRoot: bytesutil.PadTo(signingRoot, 32),
BodyRoot: params2.BeaconConfig().ZeroHash[:],
}
signRoot, err := header.HashTreeRoot()
if err != nil {
t.Fatal(err)
}
someSig := make([]byte, params2.BeaconConfig().BLSSignatureLength)
copy(someSig, "foobar")
return &slashertypes.SignedBlockHeaderWrapper{
SignedBeaconBlockHeader: &ethpb.SignedBeaconBlockHeader{
Header: header,
Signature: someSig,
},
SigningRoot: signRoot,
}
}

View File

@@ -0,0 +1,64 @@
package slasher
import (
"context"
slashertypes "github.com/prysmaticlabs/prysm/beacon-chain/slasher/types"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// IsSlashableBlock checks if an input block header is slashable
// with respect to historical block proposal data.
func (s *Service) IsSlashableBlock(
ctx context.Context, block *ethpb.SignedBeaconBlockHeader,
) (*ethpb.ProposerSlashing, error) {
dataRoot, err := block.Header.HashTreeRoot()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get block header hash tree root: %v", err)
}
signedBlockWrapper := &slashertypes.SignedBlockHeaderWrapper{
SignedBeaconBlockHeader: block,
SigningRoot: dataRoot,
}
proposerSlashings, err := s.detectProposerSlashings(ctx, []*slashertypes.SignedBlockHeaderWrapper{signedBlockWrapper})
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if proposal is slashable: %v", err)
}
if len(proposerSlashings) == 0 {
return nil, nil
}
return proposerSlashings[0], nil
}
// IsSlashableAttestation checks if an input indexed attestation is slashable
// with respect to historical attestation data.
func (s *Service) IsSlashableAttestation(
ctx context.Context, attestation *ethpb.IndexedAttestation,
) ([]*ethpb.AttesterSlashing, error) {
dataRoot, err := attestation.Data.HashTreeRoot()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get attestation data hash tree root: %v", err)
}
indexedAttWrapper := &slashertypes.IndexedAttestationWrapper{
IndexedAttestation: attestation,
SigningRoot: dataRoot,
}
attesterSlashings, err := s.checkSlashableAttestations(ctx, []*slashertypes.IndexedAttestationWrapper{indexedAttWrapper})
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not check if attestation is slashable: %v", err)
}
if len(attesterSlashings) == 0 {
// If the incoming attestations are not slashable, we mark them as saved in
// slasher's DB storage to help us with future detection.
if err := s.serviceCfg.Database.SaveAttestationRecordsForValidators(
ctx, []*slashertypes.IndexedAttestationWrapper{indexedAttWrapper},
); err != nil {
return nil, status.Errorf(codes.Internal, "Could not save attestation records to DB: %v", err)
}
return nil, nil
}
return attesterSlashings, nil
}

View File

@@ -0,0 +1,137 @@
package slasher
import (
"context"
"testing"
"time"
types "github.com/prysmaticlabs/eth2-types"
dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
slashertypes "github.com/prysmaticlabs/prysm/beacon-chain/slasher/types"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestIsSlashableBlock(t *testing.T) {
ctx := context.Background()
slasherDB := dbtest.SetupSlasherDB(t)
s := &Service{
serviceCfg: &ServiceConfig{
Database: slasherDB,
},
params: DefaultParams(),
blksQueue: newBlocksQueue(),
}
err := slasherDB.SaveBlockProposals(ctx, []*slashertypes.SignedBlockHeaderWrapper{
createProposalWrapper(t, 2, 3, []byte{1}),
createProposalWrapper(t, 3, 3, []byte{1}),
})
require.NoError(t, err)
tests := []struct {
name string
blockToCheck *slashertypes.SignedBlockHeaderWrapper
shouldBeSlashable bool
}{
{
name: "should not detect if same signing root",
blockToCheck: createProposalWrapper(t, 2, 3, []byte{1}),
shouldBeSlashable: false,
},
{
name: "should not detect if different slot",
blockToCheck: createProposalWrapper(t, 1, 3, []byte{2}),
shouldBeSlashable: false,
},
{
name: "should not detect if different validator index",
blockToCheck: createProposalWrapper(t, 2, 4, []byte{2}),
shouldBeSlashable: false,
},
{
name: "detects differing signing root",
blockToCheck: createProposalWrapper(t, 2, 3, []byte{2}),
shouldBeSlashable: true,
},
{
name: "should detect another slot",
blockToCheck: createProposalWrapper(t, 3, 3, []byte{2}),
shouldBeSlashable: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
proposerSlashing, err := s.IsSlashableBlock(ctx, tt.blockToCheck.SignedBeaconBlockHeader)
require.NoError(t, err)
assert.Equal(t, tt.shouldBeSlashable, proposerSlashing != nil)
})
}
}
func TestIsSlashableAttestation(t *testing.T) {
ctx := context.Background()
slasherDB := dbtest.SetupSlasherDB(t)
currentEpoch := types.Epoch(3)
currentTime := time.Now()
totalSlots := uint64(currentEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)
secondsSinceGenesis := time.Duration(totalSlots * params.BeaconConfig().SecondsPerSlot)
genesisTime := currentTime.Add(-secondsSinceGenesis * time.Second)
s := &Service{
serviceCfg: &ServiceConfig{
Database: slasherDB,
},
params: DefaultParams(),
blksQueue: newBlocksQueue(),
genesisTime: genesisTime,
}
prevAtts := []*slashertypes.IndexedAttestationWrapper{
createAttestationWrapper(t, 2, 3, []uint64{0}, []byte{1}),
createAttestationWrapper(t, 2, 3, []uint64{1}, []byte{1}),
}
err := slasherDB.SaveAttestationRecordsForValidators(ctx, prevAtts)
require.NoError(t, err)
attesterSlashings, err := s.checkSlashableAttestations(ctx, prevAtts)
require.NoError(t, err)
require.Equal(t, 0, len(attesterSlashings))
tests := []struct {
name string
attToCheck *slashertypes.IndexedAttestationWrapper
amtSlashable uint64
}{
{
name: "should not detect if same attestation data",
attToCheck: createAttestationWrapper(t, 2, 3, []uint64{1}, []byte{1}),
amtSlashable: 0,
},
{
name: "should not detect if different index",
attToCheck: createAttestationWrapper(t, 0, 3, []uint64{2}, []byte{2}),
amtSlashable: 0,
},
{
name: "should detect double if same index",
attToCheck: createAttestationWrapper(t, 0, 3, []uint64{0}, []byte{2}),
amtSlashable: 1,
},
{
name: "should detect multiple double if multiple same indices",
attToCheck: createAttestationWrapper(t, 0, 3, []uint64{0, 1}, []byte{2}),
amtSlashable: 2,
},
{
name: "should detect multiple surround if multiple same indices",
attToCheck: createAttestationWrapper(t, 1, 4, []uint64{0, 1}, []byte{2}),
amtSlashable: 2,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
attesterSlashings, err = s.IsSlashableAttestation(ctx, tt.attToCheck.IndexedAttestation)
require.NoError(t, err)
assert.Equal(t, tt.amtSlashable, uint64(len(attesterSlashings)))
})
}
}

View File

@@ -0,0 +1,99 @@
package slasher
import (
"context"
"io/ioutil"
"testing"
"time"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/async/event"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
dbtest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
mockSync "github.com/prysmaticlabs/prysm/beacon-chain/sync/initial-sync/testing"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/testing/util"
"github.com/prysmaticlabs/prysm/time/slots"
"github.com/sirupsen/logrus"
logTest "github.com/sirupsen/logrus/hooks/test"
)
var _ = SlashingChecker(&Service{})
var _ = SlashingChecker(&MockSlashingChecker{})
func TestMain(m *testing.M) {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(ioutil.Discard)
m.Run()
}
func TestService_StartStop_ChainStartEvent(t *testing.T) {
slasherDB := dbtest.SetupSlasherDB(t)
hook := logTest.NewGlobal()
beaconState, err := util.NewBeaconState()
require.NoError(t, err)
currentSlot := types.Slot(4)
require.NoError(t, beaconState.SetSlot(currentSlot))
mockChain := &mock.ChainService{
State: beaconState,
Slot: &currentSlot,
}
srv, err := New(context.Background(), &ServiceConfig{
IndexedAttestationsFeed: new(event.Feed),
BeaconBlockHeadersFeed: new(event.Feed),
StateNotifier: &mock.MockStateNotifier{},
Database: slasherDB,
HeadStateFetcher: mockChain,
SyncChecker: &mockSync.Sync{IsSyncing: false},
})
require.NoError(t, err)
go srv.Start()
time.Sleep(time.Millisecond * 100)
srv.serviceCfg.StateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.ChainStarted,
Data: &statefeed.ChainStartedData{StartTime: time.Now()},
})
time.Sleep(time.Millisecond * 100)
srv.slotTicker = &slots.SlotTicker{}
require.NoError(t, srv.Stop())
require.NoError(t, srv.Status())
require.LogsContain(t, hook, "received chain start event")
}
func TestService_StartStop_ChainAlreadyInitialized(t *testing.T) {
slasherDB := dbtest.SetupSlasherDB(t)
hook := logTest.NewGlobal()
beaconState, err := util.NewBeaconState()
require.NoError(t, err)
currentSlot := types.Slot(4)
require.NoError(t, beaconState.SetSlot(currentSlot))
mockChain := &mock.ChainService{
State: beaconState,
Slot: &currentSlot,
}
srv, err := New(context.Background(), &ServiceConfig{
IndexedAttestationsFeed: new(event.Feed),
BeaconBlockHeadersFeed: new(event.Feed),
StateNotifier: &mock.MockStateNotifier{},
Database: slasherDB,
HeadStateFetcher: mockChain,
SyncChecker: &mockSync.Sync{IsSyncing: false},
})
require.NoError(t, err)
go srv.Start()
time.Sleep(time.Millisecond * 100)
srv.serviceCfg.StateNotifier.StateFeed().Send(&feed.Event{
Type: statefeed.Initialized,
Data: &statefeed.InitializedData{StartTime: time.Now()},
})
time.Sleep(time.Millisecond * 100)
srv.slotTicker = &slots.SlotTicker{}
require.NoError(t, srv.Stop())
require.NoError(t, srv.Status())
require.LogsContain(t, hook, "chain already initialized")
}

View File

@@ -10,8 +10,8 @@ go_library(
visibility = [
"//beacon-chain:__subpackages__",
"//contracts/deposit:__subpackages__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/testing:__subpackages__",
"//shared/aggregation:__subpackages__",
"//slasher/rpc:__subpackages__",
"//testing/benchmark:__pkg__",
"//testing/fuzz:__pkg__",

View File

@@ -18,6 +18,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/stategen",
visibility = [
"//beacon-chain:__subpackages__",
"//testing/endtoend:__subpackages__",
"//testing/fuzz:__pkg__",
"//testing/slasher/simulator:__pkg__",
],

View File

@@ -6,8 +6,10 @@ go_library(
"array_root.go",
"block_header_root.go",
"eth1_root.go",
"participation_bit_root.go",
"pending_attestation_root.go",
"reference.go",
"sync_committee.root.go",
"trie_helpers.go",
"validator_map_handler.go",
"validator_root.go",
@@ -16,8 +18,8 @@ go_library(
visibility = [
"//beacon-chain:__subpackages__",
"//proto/migration:__subpackages__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/testing:__subpackages__",
"//shared/blockutil:__subpackages__",
"//slasher:__subpackages__",
"//testing:__subpackages__",
"//testing/fuzz:__pkg__",

View File

@@ -1,4 +1,4 @@
package v2
package stateutil
import (
"encoding/binary"
@@ -9,9 +9,9 @@ import (
"github.com/prysmaticlabs/prysm/encoding/ssz"
)
// participationBitsRoot computes the HashTreeRoot merkleization of
// ParticipationBitsRoot computes the HashTreeRoot merkleization of
// participation roots.
func participationBitsRoot(bits []byte) ([32]byte, error) {
func ParticipationBitsRoot(bits []byte) ([32]byte, error) {
hasher := hash.CustomSHA256Hasher()
chunkedRoots, err := packParticipationBits(bits)
if err != nil {

View File

@@ -1,4 +1,4 @@
package v2
package stateutil
import (
"github.com/prysmaticlabs/prysm/crypto/hash"
@@ -6,10 +6,10 @@ import (
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// syncCommitteeRoot computes the HashTreeRoot Merkleization of a commitee root.
// SyncCommitteeRoot computes the HashTreeRoot Merkleization of a commitee root.
// a SyncCommitteeRoot struct according to the eth2
// Simple Serialize specification.
func syncCommitteeRoot(committee *ethpb.SyncCommittee) ([32]byte, error) {
func SyncCommitteeRoot(committee *ethpb.SyncCommittee) ([32]byte, error) {
hasher := hash.CustomSHA256Hasher()
var fieldRoots [][32]byte
if committee == nil {

View File

@@ -32,9 +32,9 @@ go_library(
"//beacon-chain:__subpackages__",
"//contracts/deposit:__subpackages__",
"//proto/migration:__subpackages__",
"//proto/prysm/v1alpha1:__subpackages__",
"//proto/testing:__subpackages__",
"//runtime/interop:__subpackages__",
"//shared/aggregation:__subpackages__",
"//slasher/rpc:__subpackages__",
"//testing/benchmark:__pkg__",
"//testing/fuzz:__pkg__",

View File

@@ -6,8 +6,6 @@ go_library(
"deprecated_getters.go",
"deprecated_setters.go",
"field_root_eth1.go",
"field_root_participation_bit.go",
"field_root_sync_committee.go",
"field_root_validator.go",
"field_root_vector.go",
"field_roots.go",

View File

@@ -163,14 +163,14 @@ func (h *stateRootHasher) computeFieldRootsWithHasher(ctx context.Context, state
fieldRoots[14] = slashingsRootsRoot[:]
// PreviousEpochParticipation slice root.
prevParticipationRoot, err := participationBitsRoot(state.PreviousEpochParticipation)
prevParticipationRoot, err := stateutil.ParticipationBitsRoot(state.PreviousEpochParticipation)
if err != nil {
return nil, errors.Wrap(err, "could not compute previous epoch participation merkleization")
}
fieldRoots[15] = prevParticipationRoot[:]
// CurrentEpochParticipation slice root.
currParticipationRoot, err := participationBitsRoot(state.CurrentEpochParticipation)
currParticipationRoot, err := stateutil.ParticipationBitsRoot(state.CurrentEpochParticipation)
if err != nil {
return nil, errors.Wrap(err, "could not compute current epoch participation merkleization")
}
@@ -209,14 +209,14 @@ func (h *stateRootHasher) computeFieldRootsWithHasher(ctx context.Context, state
fieldRoots[21] = inactivityScoresRoot[:]
// Current sync committee root.
currentSyncCommitteeRoot, err := syncCommitteeRoot(state.CurrentSyncCommittee)
currentSyncCommitteeRoot, err := stateutil.SyncCommitteeRoot(state.CurrentSyncCommittee)
if err != nil {
return nil, errors.Wrap(err, "could not compute sync committee merkleization")
}
fieldRoots[22] = currentSyncCommitteeRoot[:]
// Next sync committee root.
nextSyncCommitteeRoot, err := syncCommitteeRoot(state.NextSyncCommittee)
nextSyncCommitteeRoot, err := stateutil.SyncCommitteeRoot(state.NextSyncCommittee)
if err != nil {
return nil, errors.Wrap(err, "could not compute sync committee merkleization")
}

View File

@@ -338,9 +338,9 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
case slashings:
return ssz.SlashingsRoot(b.state.Slashings)
case previousEpochParticipationBits:
return participationBitsRoot(b.state.PreviousEpochParticipation)
return stateutil.ParticipationBitsRoot(b.state.PreviousEpochParticipation)
case currentEpochParticipationBits:
return participationBitsRoot(b.state.CurrentEpochParticipation)
return stateutil.ParticipationBitsRoot(b.state.CurrentEpochParticipation)
case justificationBits:
return bytesutil.ToBytes32(b.state.JustificationBits), nil
case previousJustifiedCheckpoint:
@@ -352,9 +352,9 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
case inactivityScores:
return stateutil.Uint64ListRootWithRegistryLimit(b.state.InactivityScores)
case currentSyncCommittee:
return syncCommitteeRoot(b.state.CurrentSyncCommittee)
return stateutil.SyncCommitteeRoot(b.state.CurrentSyncCommittee)
case nextSyncCommittee:
return syncCommitteeRoot(b.state.NextSyncCommittee)
return stateutil.SyncCommitteeRoot(b.state.NextSyncCommittee)
}
return [32]byte{}, errors.New("invalid field index provided")
}

View File

@@ -52,6 +52,7 @@ go_library(
deps = [
"//async:go_default_library",
"//async/abool:go_default_library",
"//async/event:go_default_library",
"//beacon-chain/blockchain:go_default_library",
"//beacon-chain/cache:go_default_library",
"//beacon-chain/core:go_default_library",
@@ -89,6 +90,7 @@ go_library(
"//monitoring/tracing:go_default_library",
"//network/forks:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/attestation:go_default_library",
"//proto/prysm/v1alpha1/block:go_default_library",
"//proto/prysm/v1alpha1/metadata:go_default_library",
"//proto/prysm/v1alpha1/wrapper:go_default_library",

View File

@@ -83,7 +83,6 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) {
assert.NoError(t, err)
attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
assert.NoError(t, err)
attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
require.NoError(t, err)
hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain)
@@ -123,15 +122,11 @@ func TestProcessPendingAtts_HasBlockSaveUnAggregatedAtt(t *testing.T) {
seenUnAggregatedAttestationCache: lruwrpr.New(10),
}
sb = util.NewBeaconBlock()
r32, err := sb.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(sb)))
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, r.cfg.DB.SaveState(context.Background(), s, r32))
require.NoError(t, r.cfg.DB.SaveState(context.Background(), s, root))
r.blkRootToPendingAtts[r32] = []*ethpb.SignedAggregateAttestationAndProof{{Message: aggregateAndProof, Signature: aggreSig}}
r.blkRootToPendingAtts[root] = []*ethpb.SignedAggregateAttestationAndProof{{Message: aggregateAndProof, Signature: aggreSig}}
require.NoError(t, r.processPendingAtts(context.Background()))
atts, err := r.cfg.AttPool.UnaggregatedAttestations()
@@ -199,7 +194,6 @@ func TestProcessPendingAtts_NoBroadcastWithBadSignature(t *testing.T) {
assert.NoError(t, err)
attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
assert.NoError(t, err)
attesterDomain, err := signing.Domain(s.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, s.GenesisValidatorRoot())
require.NoError(t, err)
hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain)
@@ -273,7 +267,6 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
assert.NoError(t, err)
attestingIndices, err := attestation.AttestingIndices(att.AggregationBits, committee)
require.NoError(t, err)
assert.NoError(t, err)
attesterDomain, err := signing.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
require.NoError(t, err)
hashTreeRoot, err := signing.ComputeSigningRoot(att.Data, attesterDomain)
@@ -316,15 +309,11 @@ func TestProcessPendingAtts_HasBlockSaveAggregatedAtt(t *testing.T) {
seenAggregatedAttestationCache: lruwrpr.New(10),
}
sb = util.NewBeaconBlock()
r32, err := sb.Block.HashTreeRoot()
require.NoError(t, err)
require.NoError(t, r.cfg.DB.SaveBlock(context.Background(), wrapper.WrappedPhase0SignedBeaconBlock(sb)))
s, err := util.NewBeaconState()
require.NoError(t, err)
require.NoError(t, r.cfg.DB.SaveState(context.Background(), s, r32))
require.NoError(t, r.cfg.DB.SaveState(context.Background(), s, root))
r.blkRootToPendingAtts[r32] = []*ethpb.SignedAggregateAttestationAndProof{{Message: aggregateAndProof, Signature: aggreSig}}
r.blkRootToPendingAtts[root] = []*ethpb.SignedAggregateAttestationAndProof{{Message: aggregateAndProof, Signature: aggreSig}}
require.NoError(t, r.processPendingAtts(context.Background()))
assert.Equal(t, 1, len(r.cfg.AttPool.AggregatedAttestations()), "Did not save aggregated att")

View File

@@ -17,6 +17,7 @@ import (
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/async"
"github.com/prysmaticlabs/prysm/async/abool"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
@@ -68,18 +69,21 @@ type validationFn func(ctx context.Context) (pubsub.ValidationResult, error)
// Config to set up the regular sync service.
type Config struct {
P2P p2p.P2P
DB db.NoHeadAccessDatabase
AttPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingPool slashings.PoolManager
SyncCommsPool synccommittee.Pool
Chain blockchainService
InitialSync Checker
StateNotifier statefeed.Notifier
BlockNotifier blockfeed.Notifier
OperationNotifier operation.Notifier
StateGen *stategen.State
AttestationNotifier operation.Notifier
P2P p2p.P2P
DB db.NoHeadAccessDatabase
AttPool attestations.Pool
ExitPool voluntaryexits.PoolManager
SlashingPool slashings.PoolManager
SyncCommsPool synccommittee.Pool
Chain blockchainService
InitialSync Checker
StateNotifier statefeed.Notifier
BlockNotifier blockfeed.Notifier
OperationNotifier operation.Notifier
StateGen *stategen.State
SlasherAttestationsFeed *event.Feed
SlasherBlockHeadersFeed *event.Feed
}
// This defines the interface for interacting with block chain service

View File

@@ -17,8 +17,8 @@ import (
func TestBeaconAggregateProofSubscriber_CanSaveAggregatedAttestation(t *testing.T) {
r := &Service{
cfg: &Config{
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenUnAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -39,8 +39,8 @@ func TestBeaconAggregateProofSubscriber_CanSaveAggregatedAttestation(t *testing.
func TestBeaconAggregateProofSubscriber_CanSaveUnaggregatedAttestation(t *testing.T) {
r := &Service{
cfg: &Config{
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenUnAggregatedAttestationCache: lruwrpr.New(10),
}

View File

@@ -59,7 +59,7 @@ func (s *Service) validateAggregateAndProof(ctx context.Context, pid peer.ID, ms
// Broadcast the aggregated attestation on a feed to notify other services in the beacon node
// of a received aggregated attestation.
s.cfg.OperationNotifier.OperationFeed().Send(&feed.Event{
s.cfg.AttestationNotifier.OperationFeed().Send(&feed.Event{
Type: operation.AggregatedAttReceived,
Data: &operation.AggregatedAttReceivedData{
Attestation: m.Message,

View File

@@ -189,8 +189,8 @@ func TestValidateAggregateAndProof_NotWithinSlotRange(t *testing.T) {
Genesis: time.Now(),
State: beaconState,
},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -271,7 +271,7 @@ func TestValidateAggregateAndProof_ExistedInPool(t *testing.T) {
InitialSync: &mockSync.Sync{IsSyncing: false},
Chain: &mock.ChainService{Genesis: time.Now(),
State: beaconState},
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
blkRootToPendingAtts: make(map[[32]byte][]*ethpb.SignedAggregateAttestationAndProof),
@@ -364,8 +364,8 @@ func TestValidateAggregateAndProof_CanValidate(t *testing.T) {
Epoch: 0,
Root: att.Data.BeaconBlockRoot,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -459,8 +459,8 @@ func TestVerifyIndexInCommittee_SeenAggregatorEpoch(t *testing.T) {
Root: signedAggregateAndProof.Message.Aggregate.Data.BeaconBlockRoot,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -570,8 +570,8 @@ func TestValidateAggregateAndProof_BadBlock(t *testing.T) {
FinalizedCheckPoint: &ethpb.Checkpoint{
Epoch: 0,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}
@@ -661,8 +661,8 @@ func TestValidateAggregateAndProof_RejectWhenAttEpochDoesntEqualTargetEpoch(t *t
Epoch: 0,
Root: att.Data.BeaconBlockRoot,
}},
AttPool: attestations.NewPool(),
OperationNotifier: (&mock.ChainService{}).OperationNotifier(),
AttPool: attestations.NewPool(),
AttestationNotifier: (&mock.ChainService{}).OperationNotifier(),
},
seenAggregatedAttestationCache: lruwrpr.New(10),
}

View File

@@ -21,6 +21,7 @@ import (
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation"
"go.opencensus.io/trace"
)
@@ -63,7 +64,7 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
// of a received unaggregated attestation.
s.cfg.OperationNotifier.OperationFeed().Send(&feed.Event{
s.cfg.AttestationNotifier.OperationFeed().Send(&feed.Event{
Type: operation.UnaggregatedAttReceived,
Data: &operation.UnAggregatedAttReceivedData{
Attestation: att,
@@ -81,6 +82,35 @@ func (s *Service) validateCommitteeIndexBeaconAttestation(ctx context.Context, p
return pubsub.ValidationReject, err
}
if features.Get().EnableSlasher {
// Feed the indexed attestation to slasher if enabled. This action
// is done in the background to avoid adding more load to this critical code path.
go func() {
// Using a different context to prevent timeouts as this operation can be expensive
// and we want to avoid affecting the critical code path.
ctx := context.TODO()
preState, err := s.cfg.Chain.AttestationTargetState(ctx, att.Data.Target)
if err != nil {
log.WithError(err).Error("Could not retrieve pre state")
tracing.AnnotateError(span, err)
return
}
committee, err := helpers.BeaconCommitteeFromState(ctx, preState, att.Data.Slot, att.Data.CommitteeIndex)
if err != nil {
log.WithError(err).Error("Could not get attestation committee")
tracing.AnnotateError(span, err)
return
}
indexedAtt, err := attestation.ConvertToIndexed(ctx, att, committee)
if err != nil {
log.WithError(err).Error("Could not convert to indexed attestation")
tracing.AnnotateError(span, err)
return
}
s.cfg.SlasherAttestationsFeed.Send(indexedAtt)
}()
}
// Verify this the first attestation received for the participating validator for the slot.
if s.hasSeenCommitteeIndicesSlot(att.Data.Slot, att.Data.CommitteeIndex, att.AggregationBits) {
return pubsub.ValidationIgnore, nil

View File

@@ -38,11 +38,11 @@ func TestService_validateCommitteeIndexBeaconAttestation(t *testing.T) {
s := &Service{
cfg: &Config{
InitialSync: &mockSync.Sync{IsSyncing: false},
P2P: p,
DB: db,
Chain: chain,
OperationNotifier: (&mockChain.ChainService{}).OperationNotifier(),
InitialSync: &mockSync.Sync{IsSyncing: false},
P2P: p,
DB: db,
Chain: chain,
AttestationNotifier: (&mockChain.ChainService{}).OperationNotifier(),
},
blkRootToPendingAtts: make(map[[32]byte][]*ethpb.SignedAggregateAttestationAndProof),
seenUnAggregatedAttestationCache: lruwrpr.New(10),

View File

@@ -15,6 +15,7 @@ import (
blockfeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/block"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/monitoring/tracing"
@@ -70,6 +71,18 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
},
})
if features.Get().EnableSlasher {
// Feed the block header to slasher if enabled. This action
// is done in the background to avoid adding more load to this critical code path.
go func() {
blockHeader, err := block.SignedBeaconBlockHeaderFromBlockInterface(blk)
if err != nil {
log.WithError(err).WithField("blockSlot", blk.Block().Slot()).Warn("Could not extract block header")
}
s.cfg.SlasherBlockHeadersFeed.Send(blockHeader)
}()
}
// Verify the block is the first block received for the proposer for the slot.
if s.hasSeenBlockIndexSlot(blk.Block().Slot(), blk.Block().ProposerIndex()) {
return pubsub.ValidationIgnore, nil
@@ -149,6 +162,7 @@ func (s *Service) validateBeaconBlockPubSub(ctx context.Context, pid peer.ID, ms
if err := s.validateBeaconBlock(ctx, blk, blockRoot); err != nil {
return pubsub.ValidationReject, err
}
// Record attribute of valid block.
span.AddAttributes(trace.Int64Attribute("slotInEpoch", int64(blk.Block().Slot()%params.BeaconConfig().SlotsPerEpoch)))
msg.ValidatorData = blk.Proto() // Used in downstream subscriber

View File

@@ -39,9 +39,9 @@ type Flags struct {
PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.
// Feature related flags.
RemoteSlasherProtection bool // RemoteSlasherProtection utilizes a beacon node with --slasher mode for validator slashing protection.
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
SkipBLSVerify bool // Skips BLS verification across the runtime.
SlasherProtection bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher.
EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p.
EnableLargerGossipHistory bool // EnableLargerGossipHistory increases the gossip history we store in our caches.
WriteWalletPasswordOnWebOnboarding bool // WriteWalletPasswordOnWebOnboarding writes the password to disk after Prysm web signup.
@@ -66,6 +66,7 @@ type Flags struct {
// Bug fixes related flags.
AttestTimely bool // AttestTimely fixes #8185. It is gated behind a flag to ensure beacon node's fix can safely roll out first. We'll invert this in v1.1.0.
EnableSlasher bool // Enable slasher in the beacon node runtime.
// EnableSlashingProtectionPruning for the validator client.
EnableSlashingProtectionPruning bool
@@ -180,6 +181,10 @@ func ConfigureBeaconChain(ctx *cli.Context) {
logDisabled(disableNextSlotStateCache)
cfg.EnableNextSlotStateCache = false
}
if ctx.Bool(enableSlasherFlag.Name) {
log.WithField(enableSlasherFlag.Name, enableSlasherFlag.Usage).Warn(enabledFeatureFlag)
cfg.EnableSlasher = true
}
cfg.ProposerAttsSelectionUsingMaxCover = true
if ctx.Bool(disableProposerAttsSelectionUsingMaxCover.Name) {
logDisabled(disableProposerAttsSelectionUsingMaxCover)
@@ -223,8 +228,8 @@ func ConfigureValidator(ctx *cli.Context) {
cfg := &Flags{}
configureTestnet(ctx, cfg)
if ctx.Bool(enableExternalSlasherProtectionFlag.Name) {
logEnabled(enableExternalSlasherProtectionFlag)
cfg.SlasherProtection = true
log.WithField(enableExternalSlasherProtectionFlag.Name, enableExternalSlasherProtectionFlag.Usage).Warn(enabledFeatureFlag)
cfg.RemoteSlasherProtection = true
}
if ctx.Bool(writeWalletPasswordOnWebOnboarding.Name) {
logEnabled(writeWalletPasswordOnWebOnboarding)

View File

@@ -33,8 +33,8 @@ var (
}
enableExternalSlasherProtectionFlag = &cli.BoolFlag{
Name: "enable-external-slasher-protection",
Usage: "Enables the validator to connect to external slasher to prevent it from " +
"transmitting a slashable offence over the network.",
Usage: "Enables the validator to connect to a beacon node using the --slasher flag" +
"for remote slashing protection",
}
disableLookbackFlag = &cli.BoolFlag{
Name: "disable-lookback",
@@ -93,6 +93,10 @@ var (
Name: "disable-next-slot-state-cache",
Usage: "Disable next slot cache which improves attesting and proposing efficiency by caching the next slot state at the end of the current slot",
}
enableSlasherFlag = &cli.BoolFlag{
Name: "slasher",
Usage: "Enables a slasher in the beacon node for detecting slashable offenses",
}
disableProposerAttsSelectionUsingMaxCover = &cli.BoolFlag{
Name: "disable-proposer-atts-selection-using-max-cover",
Usage: "Disable max-cover algorithm when selecting attestations for proposer",
@@ -178,6 +182,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
disableBroadcastSlashingFlag,
disableNextSlotStateCache,
forceOptMaxCoverAggregationStategy,
enableSlasherFlag,
disableProposerAttsSelectionUsingMaxCover,
disableOptimizedBalanceUpdate,
enableHistoricalSpaceRepresentation,

View File

@@ -6,6 +6,7 @@
mock_path="shared/mock"
mocks=(
"$mock_path/beacon_service_mock.go BeaconChainClient,BeaconChain_StreamChainHeadClient,BeaconChain_StreamAttestationsClient,BeaconChain_StreamBlocksClient,BeaconChain_StreamValidatorsInfoClient,BeaconChain_StreamIndexedAttestationsClient"
"$mock_path/slasher_service_mock.go SlasherClient"
"$mock_path/beacon_chain_service_mock.go BeaconChain_StreamChainHeadServer,BeaconChain_StreamAttestationsServer,BeaconChain_StreamBlocksServer,BeaconChain_StreamValidatorsInfoServer,BeaconChain_StreamIndexedAttestationsServer"
"$mock_path/beacon_validator_server_mock.go BeaconNodeValidatorServer,BeaconNodeValidator_WaitForActivationServer,BeaconNodeValidator_WaitForChainStartServer,BeaconNodeValidator_StreamDutiesServer"
"$mock_path/beacon_validator_client_mock.go BeaconNodeValidatorClient,BeaconNodeValidator_WaitForChainStartClient,BeaconNodeValidator_WaitForActivationClient,BeaconNodeValidator_StreamDutiesClient"
@@ -19,7 +20,6 @@ for ((i = 0; i < ${#mocks[@]}; i++)); do
interfaces=${mocks[i]#* };
echo "generating $file for interfaces: $interfaces";
GO11MODULE=on mockgen -package=mock -destination="$file" github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1 "$interfaces"
GO11MODULE=on mockgen -package=mock -destination="$file" github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1 "$interfaces"
done
goimports -w "$mock_path/."

View File

@@ -64,7 +64,7 @@
"external/.*": "Third party code",
"rules_go_work-.*": "Third party code",
"config/params/config.go": "This config struct needs to be organized for now",
"shared/featureconfig/config.go": "This config struct needs to be organized for now",
"config/features/config.go": "This config struct needs to be organized for now",
"proto/.*": "Excluding protobuf objects for now"
}
},

View File

@@ -541,7 +541,7 @@ var file_proto_prysm_v1alpha1_slasher_proto_rawDesc = []byte{
0x63, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
0x02, 0x38, 0x01, 0x32, 0xf1, 0x05, 0x0a, 0x07, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x72, 0x12,
0x02, 0x38, 0x01, 0x32, 0x90, 0x04, 0x0a, 0x07, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x72, 0x12,
0xad, 0x01, 0x0a, 0x16, 0x49, 0x73, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x41,
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68,
0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
@@ -563,42 +563,28 @@ var file_proto_prysm_v1alpha1_slasher_proto_rawDesc = []byte{
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x28, 0x12, 0x26, 0x2f,
0x65, 0x74, 0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x6c, 0x61,
0x73, 0x68, 0x65, 0x72, 0x2f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2f, 0x73, 0x6c, 0x61, 0x73,
0x68, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x1e, 0x49, 0x73, 0x53, 0x6c, 0x61, 0x73, 0x68,
0x61, 0x62, 0x6c, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e,
0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65,
0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x1a, 0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74,
0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x6c, 0x61, 0x73, 0x68,
0x61, 0x62, 0x6c, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0x6b, 0x0a, 0x18, 0x49, 0x73, 0x53,
0x6c, 0x61, 0x73, 0x68, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x6f, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x28, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x42, 0x65,
0x61, 0x63, 0x6f, 0x6e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a,
0x20, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x61, 0x62, 0x6c,
0x65, 0x22, 0x03, 0x88, 0x02, 0x01, 0x12, 0xae, 0x01, 0x0a, 0x13, 0x48, 0x69, 0x67, 0x68, 0x65,
0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30,
0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x41, 0x74,
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74,
0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x65, 0x74,
0x68, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x6c, 0x61, 0x73, 0x68,
0x65, 0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f,
0x68, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x94, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e,
0x68, 0x61, 0x62, 0x6c, 0x65, 0x12, 0xae, 0x01, 0x0a, 0x13, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73,
0x74, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x2e,
0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x72, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f,
0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73,
0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02,
0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
0x6d, 0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x41, 0x74, 0x74,
0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x31, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x41,
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x12, 0x2a, 0x2f, 0x65, 0x74, 0x68,
0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2f, 0x73, 0x6c, 0x61, 0x73, 0x68, 0x65,
0x72, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x68,
0x69, 0x67, 0x68, 0x65, 0x73, 0x74, 0x42, 0x94, 0x01, 0x0a, 0x19, 0x6f, 0x72, 0x67, 0x2e, 0x65,
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x74, 0x68, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x42, 0x0c, 0x53, 0x6c, 0x61, 0x73, 0x68, 0x65, 0x72, 0x50, 0x72, 0x6f,
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70,
0x72, 0x79, 0x73, 0x6d, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d,
0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x65, 0x74, 0x68, 0xaa, 0x02, 0x15,
0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x74, 0x68, 0x2e, 0x56, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x15, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d,
0x5c, 0x45, 0x74, 0x68, 0x5c, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -628,7 +614,6 @@ var file_proto_prysm_v1alpha1_slasher_proto_goTypes = []interface{}{
(*ProposerSlashing)(nil), // 10: ethereum.eth.v1alpha1.ProposerSlashing
(*IndexedAttestation)(nil), // 11: ethereum.eth.v1alpha1.IndexedAttestation
(*SignedBeaconBlockHeader)(nil), // 12: ethereum.eth.v1alpha1.SignedBeaconBlockHeader
(*BeaconBlockHeader)(nil), // 13: ethereum.eth.v1alpha1.BeaconBlockHeader
}
var file_proto_prysm_v1alpha1_slasher_proto_depIdxs = []int32{
9, // 0: ethereum.eth.v1alpha1.AttesterSlashingResponse.attester_slashings:type_name -> ethereum.eth.v1alpha1.AttesterSlashing
@@ -637,16 +622,12 @@ var file_proto_prysm_v1alpha1_slasher_proto_depIdxs = []int32{
8, // 3: ethereum.eth.v1alpha1.AttestationHistory.target_to_source:type_name -> ethereum.eth.v1alpha1.AttestationHistory.TargetToSourceEntry
11, // 4: ethereum.eth.v1alpha1.Slasher.IsSlashableAttestation:input_type -> ethereum.eth.v1alpha1.IndexedAttestation
12, // 5: ethereum.eth.v1alpha1.Slasher.IsSlashableBlock:input_type -> ethereum.eth.v1alpha1.SignedBeaconBlockHeader
11, // 6: ethereum.eth.v1alpha1.Slasher.IsSlashableAttestationNoUpdate:input_type -> ethereum.eth.v1alpha1.IndexedAttestation
13, // 7: ethereum.eth.v1alpha1.Slasher.IsSlashableBlockNoUpdate:input_type -> ethereum.eth.v1alpha1.BeaconBlockHeader
2, // 8: ethereum.eth.v1alpha1.Slasher.HighestAttestations:input_type -> ethereum.eth.v1alpha1.HighestAttestationRequest
0, // 9: ethereum.eth.v1alpha1.Slasher.IsSlashableAttestation:output_type -> ethereum.eth.v1alpha1.AttesterSlashingResponse
1, // 10: ethereum.eth.v1alpha1.Slasher.IsSlashableBlock:output_type -> ethereum.eth.v1alpha1.ProposerSlashingResponse
6, // 11: ethereum.eth.v1alpha1.Slasher.IsSlashableAttestationNoUpdate:output_type -> ethereum.eth.v1alpha1.Slashable
6, // 12: ethereum.eth.v1alpha1.Slasher.IsSlashableBlockNoUpdate:output_type -> ethereum.eth.v1alpha1.Slashable
3, // 13: ethereum.eth.v1alpha1.Slasher.HighestAttestations:output_type -> ethereum.eth.v1alpha1.HighestAttestationResponse
9, // [9:14] is the sub-list for method output_type
4, // [4:9] is the sub-list for method input_type
2, // 6: ethereum.eth.v1alpha1.Slasher.HighestAttestations:input_type -> ethereum.eth.v1alpha1.HighestAttestationRequest
0, // 7: ethereum.eth.v1alpha1.Slasher.IsSlashableAttestation:output_type -> ethereum.eth.v1alpha1.AttesterSlashingResponse
1, // 8: ethereum.eth.v1alpha1.Slasher.IsSlashableBlock:output_type -> ethereum.eth.v1alpha1.ProposerSlashingResponse
3, // 9: ethereum.eth.v1alpha1.Slasher.HighestAttestations:output_type -> ethereum.eth.v1alpha1.HighestAttestationResponse
7, // [7:10] is the sub-list for method output_type
4, // [4:7] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
@@ -790,10 +771,6 @@ const _ = grpc.SupportPackageIsVersion6
type SlasherClient interface {
IsSlashableAttestation(ctx context.Context, in *IndexedAttestation, opts ...grpc.CallOption) (*AttesterSlashingResponse, error)
IsSlashableBlock(ctx context.Context, in *SignedBeaconBlockHeader, opts ...grpc.CallOption) (*ProposerSlashingResponse, error)
// Deprecated: Do not use.
IsSlashableAttestationNoUpdate(ctx context.Context, in *IndexedAttestation, opts ...grpc.CallOption) (*Slashable, error)
// Deprecated: Do not use.
IsSlashableBlockNoUpdate(ctx context.Context, in *BeaconBlockHeader, opts ...grpc.CallOption) (*Slashable, error)
HighestAttestations(ctx context.Context, in *HighestAttestationRequest, opts ...grpc.CallOption) (*HighestAttestationResponse, error)
}
@@ -823,26 +800,6 @@ func (c *slasherClient) IsSlashableBlock(ctx context.Context, in *SignedBeaconBl
return out, nil
}
// Deprecated: Do not use.
func (c *slasherClient) IsSlashableAttestationNoUpdate(ctx context.Context, in *IndexedAttestation, opts ...grpc.CallOption) (*Slashable, error) {
out := new(Slashable)
err := c.cc.Invoke(ctx, "/ethereum.eth.v1alpha1.Slasher/IsSlashableAttestationNoUpdate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Deprecated: Do not use.
func (c *slasherClient) IsSlashableBlockNoUpdate(ctx context.Context, in *BeaconBlockHeader, opts ...grpc.CallOption) (*Slashable, error) {
out := new(Slashable)
err := c.cc.Invoke(ctx, "/ethereum.eth.v1alpha1.Slasher/IsSlashableBlockNoUpdate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *slasherClient) HighestAttestations(ctx context.Context, in *HighestAttestationRequest, opts ...grpc.CallOption) (*HighestAttestationResponse, error) {
out := new(HighestAttestationResponse)
err := c.cc.Invoke(ctx, "/ethereum.eth.v1alpha1.Slasher/HighestAttestations", in, out, opts...)
@@ -856,10 +813,6 @@ func (c *slasherClient) HighestAttestations(ctx context.Context, in *HighestAtte
type SlasherServer interface {
IsSlashableAttestation(context.Context, *IndexedAttestation) (*AttesterSlashingResponse, error)
IsSlashableBlock(context.Context, *SignedBeaconBlockHeader) (*ProposerSlashingResponse, error)
// Deprecated: Do not use.
IsSlashableAttestationNoUpdate(context.Context, *IndexedAttestation) (*Slashable, error)
// Deprecated: Do not use.
IsSlashableBlockNoUpdate(context.Context, *BeaconBlockHeader) (*Slashable, error)
HighestAttestations(context.Context, *HighestAttestationRequest) (*HighestAttestationResponse, error)
}
@@ -873,12 +826,6 @@ func (*UnimplementedSlasherServer) IsSlashableAttestation(context.Context, *Inde
func (*UnimplementedSlasherServer) IsSlashableBlock(context.Context, *SignedBeaconBlockHeader) (*ProposerSlashingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsSlashableBlock not implemented")
}
func (*UnimplementedSlasherServer) IsSlashableAttestationNoUpdate(context.Context, *IndexedAttestation) (*Slashable, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsSlashableAttestationNoUpdate not implemented")
}
func (*UnimplementedSlasherServer) IsSlashableBlockNoUpdate(context.Context, *BeaconBlockHeader) (*Slashable, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsSlashableBlockNoUpdate not implemented")
}
func (*UnimplementedSlasherServer) HighestAttestations(context.Context, *HighestAttestationRequest) (*HighestAttestationResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method HighestAttestations not implemented")
}
@@ -923,42 +870,6 @@ func _Slasher_IsSlashableBlock_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _Slasher_IsSlashableAttestationNoUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IndexedAttestation)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SlasherServer).IsSlashableAttestationNoUpdate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ethereum.eth.v1alpha1.Slasher/IsSlashableAttestationNoUpdate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SlasherServer).IsSlashableAttestationNoUpdate(ctx, req.(*IndexedAttestation))
}
return interceptor(ctx, in, info, handler)
}
func _Slasher_IsSlashableBlockNoUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BeaconBlockHeader)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(SlasherServer).IsSlashableBlockNoUpdate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/ethereum.eth.v1alpha1.Slasher/IsSlashableBlockNoUpdate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SlasherServer).IsSlashableBlockNoUpdate(ctx, req.(*BeaconBlockHeader))
}
return interceptor(ctx, in, info, handler)
}
func _Slasher_HighestAttestations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(HighestAttestationRequest)
if err := dec(in); err != nil {
@@ -989,14 +900,6 @@ var _Slasher_serviceDesc = grpc.ServiceDesc{
MethodName: "IsSlashableBlock",
Handler: _Slasher_IsSlashableBlock_Handler,
},
{
MethodName: "IsSlashableAttestationNoUpdate",
Handler: _Slasher_IsSlashableAttestationNoUpdate_Handler,
},
{
MethodName: "IsSlashableBlockNoUpdate",
Handler: _Slasher_IsSlashableBlockNoUpdate_Handler,
},
{
MethodName: "HighestAttestations",
Handler: _Slasher_HighestAttestations_Handler,

View File

@@ -49,22 +49,6 @@ service Slasher {
};
}
// Returns if a given indexed attestation could be slashable when compared to
// the slashers history for the attesters. This function is read-only, and
// does not need the indexed attestation to be signed.
rpc IsSlashableAttestationNoUpdate(ethereum.eth.v1alpha1.IndexedAttestation)
returns (Slashable) {
option deprecated = true;
};
// Returns if a given beacon block header could be slashable when compared to
// the slashers history for the proposer. This function is read-only, and does
// not need the beacon block header to be signed.
rpc IsSlashableBlockNoUpdate(ethereum.eth.v1alpha1.BeaconBlockHeader)
returns (Slashable) {
option deprecated = true;
};
// Returns the highest source and target attestation for validator indices
// that have been observed by slasher.
rpc HighestAttestations(HighestAttestationRequest)

View File

@@ -26,6 +26,7 @@ go_library(
"//async/event:go_default_library",
"//beacon-chain/core:go_default_library",
"//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//cache/lru:go_default_library",
"//config/features:go_default_library",
@@ -53,7 +54,6 @@ go_library(
"//validator/keymanager:go_default_library",
"//validator/keymanager/imported:go_default_library",
"//validator/keymanager/remote:go_default_library",
"//validator/slashing-protection/iface:go_default_library",
"@com_github_dgraph_io_ristretto//:go_default_library",
"@com_github_ferranbt_fastssz//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",

View File

@@ -81,8 +81,12 @@ func (v *validator) slashableAttestationCheck(
return errors.Wrap(err, "could not save attestation history for validator public key")
}
if features.Get().SlasherProtection && v.protector != nil {
if !v.protector.CommitAttestation(ctx, indexedAtt) {
if features.Get().RemoteSlasherProtection {
slashing, err := v.slashingProtectionClient.IsSlashableAttestation(ctx, indexedAtt)
if err != nil {
return errors.Wrap(err, "could not check if attestation is slashable")
}
if slashing != nil && len(slashing.AttesterSlashings) > 0 {
if v.emitAccountMetrics {
ValidatorAttestFailVecSlasher.WithLabelValues(fmtKey).Inc()
}

View File

@@ -10,16 +10,15 @@ import (
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/require"
mockSlasher "github.com/prysmaticlabs/prysm/validator/testing"
)
func Test_slashableAttestationCheck(t *testing.T) {
config := &features.Flags{
SlasherProtection: true,
RemoteSlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
validator, _, validatorKey, finish := setup(t)
validator, m, validatorKey, finish := setup(t)
defer finish()
pubKey := [48]byte{}
copy(pubKey[:], validatorKey.PublicKey().Marshal())
@@ -39,18 +38,30 @@ func Test_slashableAttestationCheck(t *testing.T) {
},
},
}
mockProtector := &mockSlasher.MockProtector{AllowAttestation: false}
validator.protector = mockProtector
m.slasherClient.EXPECT().IsSlashableAttestation(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.AttesterSlashingResponse{AttesterSlashings: []*ethpb.AttesterSlashing{{
Attestation_1: &ethpb.IndexedAttestation{},
Attestation_2: &ethpb.IndexedAttestation{},
}}}, nil /*err*/)
err := validator.slashableAttestationCheck(context.Background(), att, pubKey, [32]byte{1})
require.ErrorContains(t, failedPostAttSignExternalErr, err)
mockProtector.AllowAttestation = true
m.slasherClient.EXPECT().IsSlashableAttestation(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.AttesterSlashingResponse{}, nil /*err*/)
err = validator.slashableAttestationCheck(context.Background(), att, pubKey, [32]byte{1})
require.NoError(t, err, "Expected allowed attestation not to throw error")
}
func Test_slashableAttestationCheck_UpdatesLowestSignedEpochs(t *testing.T) {
config := &features.Flags{
SlasherProtection: true,
RemoteSlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
@@ -75,18 +86,23 @@ func Test_slashableAttestationCheck_UpdatesLowestSignedEpochs(t *testing.T) {
},
},
}
mockProtector := &mockSlasher.MockProtector{AllowAttestation: false}
validator.protector = mockProtector
m.slasherClient.EXPECT().IsSlashableAttestation(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.AttesterSlashingResponse{}, nil /*err*/)
m.validatorClient.EXPECT().DomainData(
gomock.Any(), // ctx
&ethpb.DomainRequest{Epoch: 10, Domain: []byte{1, 0, 0, 0}},
).Return(&ethpb.DomainResponse{SignatureDomain: make([]byte, 32)}, nil /*err*/)
_, sr, err := validator.getDomainAndSigningRoot(ctx, att.Data)
require.NoError(t, err)
mockProtector.AllowAttestation = true
err = validator.slashableAttestationCheck(context.Background(), att, pubKey, sr)
require.NoError(t, err)
differentSigningRoot := [32]byte{2}
err = validator.slashableAttestationCheck(context.Background(), att, pubKey, differentSigningRoot)
require.ErrorContains(t, "could not sign attestation", err)
@@ -102,12 +118,12 @@ func Test_slashableAttestationCheck_UpdatesLowestSignedEpochs(t *testing.T) {
func Test_slashableAttestationCheck_OK(t *testing.T) {
config := &features.Flags{
SlasherProtection: false,
RemoteSlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
ctx := context.Background()
validator, _, _, finish := setup(t)
validator, mocks, _, finish := setup(t)
defer finish()
att := &ethpb.IndexedAttestation{
AttestingIndices: []uint64{1, 2},
@@ -127,18 +143,24 @@ func Test_slashableAttestationCheck_OK(t *testing.T) {
}
sr := [32]byte{1}
fakePubkey := bytesutil.ToBytes48([]byte("test"))
mocks.slasherClient.EXPECT().IsSlashableAttestation(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.AttesterSlashingResponse{}, nil /*err*/)
err := validator.slashableAttestationCheck(ctx, att, fakePubkey, sr)
require.NoError(t, err, "Expected allowed attestation not to throw error")
}
func Test_slashableAttestationCheck_GenesisEpoch(t *testing.T) {
config := &features.Flags{
SlasherProtection: false,
RemoteSlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
ctx := context.Background()
validator, _, _, finish := setup(t)
validator, mocks, _, finish := setup(t)
defer finish()
att := &ethpb.IndexedAttestation{
AttestingIndices: []uint64{1, 2},
@@ -156,6 +178,12 @@ func Test_slashableAttestationCheck_GenesisEpoch(t *testing.T) {
},
},
}
mocks.slasherClient.EXPECT().IsSlashableAttestation(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.AttesterSlashingResponse{}, nil /*err*/)
fakePubkey := bytesutil.ToBytes48([]byte("test"))
err := validator.slashableAttestationCheck(ctx, att, fakePubkey, [32]byte{})
require.NoError(t, err, "Expected allowed attestation not to throw error")

View File

@@ -36,7 +36,6 @@ type Validator interface {
WaitForChainStart(ctx context.Context) error
WaitForSync(ctx context.Context) error
WaitForActivation(ctx context.Context, accountsChangedChan chan [][48]byte) error
SlasherReady(ctx context.Context) error
CanonicalHeadSlot(ctx context.Context) (types.Slot, error)
NextSlot() <-chan types.Slot
SlotDeadline(slot types.Slot) time.Time

View File

@@ -119,20 +119,13 @@ func (v *validator) proposeBlockPhase0(ctx context.Context, slot types.Slot, pub
return
}
if err := v.preBlockSignValidations(ctx, pubKey, wrapper.WrappedPhase0BeaconBlock(b), signingRoot); err != nil {
if err := v.slashableProposalCheck(ctx, pubKey, wrapper.WrappedPhase0SignedBeaconBlock(blk), signingRoot); err != nil {
log.WithFields(
blockLogFields(pubKey, wrapper.WrappedPhase0BeaconBlock(b), nil),
).WithError(err).Error("Failed block slashing protection check")
return
}
if err := v.postBlockSignUpdate(ctx, pubKey, wrapper.WrappedPhase0SignedBeaconBlock(blk), signingRoot); err != nil {
log.WithFields(
blockLogFields(pubKey, wrapper.WrappedPhase0BeaconBlock(b), sig),
).WithError(err).Error("Failed block slashing protection check")
return
}
// Propose and broadcast block via beacon node
blkResp, err := v.validatorClient.ProposeBlock(ctx, blk)
if err != nil {
@@ -252,16 +245,6 @@ func (v *validator) proposeBlockAltair(ctx context.Context, slot types.Slot, pub
return
}
if err := v.preBlockSignValidations(ctx, pubKey, wb, signingRoot); err != nil {
log.WithFields(
blockLogFields(pubKey, wb, nil),
).WithError(err).Error("Failed block slashing protection check")
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
}
return
}
wsb, err := wrapper.WrappedAltairSignedBeaconBlock(blk)
if err != nil {
log.WithError(err).Error("Failed to wrap signed block")
@@ -270,9 +253,10 @@ func (v *validator) proposeBlockAltair(ctx context.Context, slot types.Slot, pub
}
return
}
if err := v.postBlockSignUpdate(ctx, pubKey, wsb, signingRoot); err != nil {
if err := v.slashableProposalCheck(ctx, pubKey, wsb, signingRoot); err != nil {
log.WithFields(
blockLogFields(pubKey, wb, sig),
blockLogFields(pubKey, wb, nil),
).WithError(err).Error("Failed block slashing protection check")
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()

View File

@@ -5,22 +5,23 @@ import (
"fmt"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block"
"github.com/sirupsen/logrus"
)
var failedPreBlockSignLocalErr = "attempted to sign a double proposal, block rejected by local protection"
var failedPreBlockSignExternalErr = "attempted a double proposal, block rejected by remote slashing protection"
var failedPostBlockSignErr = "made a double proposal, considered slashable by remote slashing protection"
var failedBlockSignLocalErr = "attempted to sign a double proposal, block rejected by local protection"
var failedBlockSignExternalErr = "attempted a double proposal, block rejected by remote slashing protection"
func (v *validator) preBlockSignValidations(
ctx context.Context, pubKey [48]byte, blk block.BeaconBlock, signingRoot [32]byte,
func (v *validator) slashableProposalCheck(
ctx context.Context, pubKey [48]byte, signedBlock block.SignedBeaconBlock, signingRoot [32]byte,
) error {
fmtKey := fmt.Sprintf("%#x", pubKey[:])
prevSigningRoot, proposalAtSlotExists, err := v.db.ProposalHistoryForSlot(ctx, pubKey, blk.Slot())
block := signedBlock.Block()
prevSigningRoot, proposalAtSlotExists, err := v.db.ProposalHistoryForSlot(ctx, pubKey, block.Slot())
if err != nil {
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
@@ -42,7 +43,7 @@ func (v *validator) preBlockSignValidations(
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
}
return errors.New(failedPreBlockSignLocalErr)
return errors.New(failedBlockSignLocalErr)
}
// Based on EIP3076, validator should refuse to sign any proposal with slot less
@@ -57,46 +58,23 @@ func (v *validator) preBlockSignValidations(
)
}
if features.Get().SlasherProtection && v.protector != nil {
blockHdr, err := block.BeaconBlockHeaderFromBlockInterface(blk)
if features.Get().RemoteSlasherProtection {
blockHdr, err := blocks.SignedBeaconBlockHeaderFromBlockInterface(signedBlock)
if err != nil {
return errors.Wrap(err, "failed to get block header from block")
}
if !v.protector.CheckBlockSafety(ctx, blockHdr) {
slashing, err := v.slashingProtectionClient.IsSlashableBlock(ctx, blockHdr)
if err != nil {
return errors.Wrap(err, "could not check if block is slashable")
}
if slashing != nil && len(slashing.ProposerSlashings) > 0 {
if v.emitAccountMetrics {
ValidatorProposeFailVecSlasher.WithLabelValues(fmtKey).Inc()
}
return errors.New(failedPreBlockSignExternalErr)
return errors.New(failedBlockSignExternalErr)
}
}
return nil
}
func (v *validator) postBlockSignUpdate(
ctx context.Context,
pubKey [48]byte,
blk block.SignedBeaconBlock,
signingRoot [32]byte,
) error {
fmtKey := fmt.Sprintf("%#x", pubKey[:])
if features.Get().SlasherProtection && v.protector != nil {
sbh, err := block.SignedBeaconBlockHeaderFromBlockInterface(blk)
if err != nil {
return errors.Wrap(err, "failed to get block header from block")
}
valid, err := v.protector.CommitBlock(ctx, sbh)
if err != nil {
return err
}
if !valid {
if v.emitAccountMetrics {
ValidatorProposeFailVecSlasher.WithLabelValues(fmtKey).Inc()
}
return fmt.Errorf(failedPostBlockSignErr)
}
}
if err := v.db.SaveProposalHistoryForSlot(ctx, pubKey, blk.Block().Slot(), signingRoot[:]); err != nil {
if err := v.db.SaveProposalHistoryForSlot(ctx, pubKey, block.Slot(), signingRoot[:]); err != nil {
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
}

View File

@@ -4,8 +4,10 @@ import (
"context"
"testing"
"github.com/golang/mock/gomock"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/config/params"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
"github.com/prysmaticlabs/prysm/testing/require"
@@ -13,7 +15,7 @@ import (
mockSlasher "github.com/prysmaticlabs/prysm/validator/testing"
)
func TestPreBlockSignLocalValidation_PreventsLowerThanMinProposal(t *testing.T) {
func Test_slashableProposalCheck_PreventsLowerThanMinProposal(t *testing.T) {
ctx := context.Background()
validator, _, validatorKey, finish := setup(t)
defer finish()
@@ -28,55 +30,64 @@ func TestPreBlockSignLocalValidation_PreventsLowerThanMinProposal(t *testing.T)
// We expect the same block with a slot lower than the lowest
// signed slot to fail validation.
block := &ethpb.BeaconBlock{
Slot: lowestSignedSlot - 1,
ProposerIndex: 0,
block := &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Slot: lowestSignedSlot - 1,
ProposerIndex: 0,
},
Signature: params.BeaconConfig().EmptySignature[:],
}
err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{4})
err = validator.slashableProposalCheck(context.Background(), pubKeyBytes, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{4})
require.ErrorContains(t, "could not sign block with slot <= lowest signed", err)
// We expect the same block with a slot equal to the lowest
// signed slot to pass validation if signing roots are equal.
block = &ethpb.BeaconBlock{
Slot: lowestSignedSlot,
ProposerIndex: 0,
block = &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Slot: lowestSignedSlot,
ProposerIndex: 0,
},
Signature: params.BeaconConfig().EmptySignature[:],
}
err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{1})
err = validator.slashableProposalCheck(context.Background(), pubKeyBytes, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{1})
require.NoError(t, err)
// We expect the same block with a slot equal to the lowest
// signed slot to fail validation if signing roots are different.
block = &ethpb.BeaconBlock{
Slot: lowestSignedSlot,
ProposerIndex: 0,
}
err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{4})
require.ErrorContains(t, failedPreBlockSignLocalErr, err)
err = validator.slashableProposalCheck(context.Background(), pubKeyBytes, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{4})
require.ErrorContains(t, failedBlockSignLocalErr, err)
// We expect the same block with a slot > than the lowest
// signed slot to pass validation.
block = &ethpb.BeaconBlock{
Slot: lowestSignedSlot + 1,
ProposerIndex: 0,
block = &ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Slot: lowestSignedSlot + 1,
ProposerIndex: 0,
},
Signature: params.BeaconConfig().EmptySignature[:],
}
err = validator.preBlockSignValidations(context.Background(), pubKeyBytes, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{3})
err = validator.slashableProposalCheck(context.Background(), pubKeyBytes, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{3})
require.NoError(t, err)
}
func TestPreBlockSignLocalValidation(t *testing.T) {
func Test_slashableProposalCheck(t *testing.T) {
ctx := context.Background()
config := &features.Flags{
SlasherProtection: false,
RemoteSlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
validator, _, validatorKey, finish := setup(t)
validator, mocks, validatorKey, finish := setup(t)
defer finish()
block := &ethpb.BeaconBlock{
Slot: 10,
ProposerIndex: 0,
}
block := util.HydrateSignedBeaconBlock(&ethpb.SignedBeaconBlock{
Block: &ethpb.BeaconBlock{
Slot: 10,
ProposerIndex: 0,
},
Signature: params.BeaconConfig().EmptySignature[:],
})
pubKeyBytes := [48]byte{}
copy(pubKeyBytes[:], validatorKey.PublicKey().Marshal())
@@ -91,71 +102,63 @@ func TestPreBlockSignLocalValidation(t *testing.T) {
pubKey := [48]byte{}
copy(pubKey[:], validatorKey.PublicKey().Marshal())
mock.slasherClient.EXPECT().IsSlashableBlock(
gomock.Any(), // ctx
gomock.Any(),
).Times(2).Return(&ethpb.ProposerSlashingResponse{}, nil /*err*/)
// We expect the same block sent out with the same root should not be slasahble.
err = validator.preBlockSignValidations(context.Background(), pubKey, wrapper.WrappedPhase0BeaconBlock(block), dummySigningRoot)
err = validator.slashableProposalCheck(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(block), dummySigningRoot)
require.NoError(t, err)
// We expect the same block sent out with a different signing root should be slasahble.
err = validator.preBlockSignValidations(context.Background(), pubKey, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{2})
require.ErrorContains(t, failedPreBlockSignLocalErr, err)
err = validator.slashableProposalCheck(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{2})
require.ErrorContains(t, failedBlockSignLocalErr, err)
// We save a proposal at slot 11 with a nil signing root.
block.Slot = 11
err = validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, block.Slot, nil)
block.Block.Slot = 11
err = validator.db.SaveProposalHistoryForSlot(ctx, pubKeyBytes, block.Block.Slot, nil)
require.NoError(t, err)
// We expect the same block sent out should return slashable error even
// if we had a nil signing root stored in the database.
err = validator.preBlockSignValidations(context.Background(), pubKey, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{2})
require.ErrorContains(t, failedPreBlockSignLocalErr, err)
err = validator.slashableProposalCheck(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{2})
require.ErrorContains(t, failedBlockSignLocalErr, err)
// A block with a different slot for which we do not have a proposing history
// should not be failing validation.
block.Slot = 9
err = validator.preBlockSignValidations(context.Background(), pubKey, wrapper.WrappedPhase0BeaconBlock(block), [32]byte{3})
block.Block.Slot = 9
err = validator.slashableProposalCheck(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{3})
require.NoError(t, err, "Expected allowed block not to throw error")
}
func TestPreBlockSignValidation(t *testing.T) {
func Test_slashableProposalCheck_RemoteProtection(t *testing.T) {
config := &features.Flags{
SlasherProtection: true,
RemoteSlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
validator, _, validatorKey, finish := setup(t)
validator, m, validatorKey, finish := setup(t)
defer finish()
pubKey := [48]byte{}
copy(pubKey[:], validatorKey.PublicKey().Marshal())
block := util.NewBeaconBlock()
block.Block.Slot = 10
mockProtector := &mockSlasher.MockProtector{AllowBlock: false}
validator.protector = mockProtector
err := validator.preBlockSignValidations(context.Background(), pubKey, wrapper.WrappedPhase0BeaconBlock(block.Block), [32]byte{2})
require.ErrorContains(t, failedPreBlockSignExternalErr, err)
mockProtector.AllowBlock = true
err = validator.preBlockSignValidations(context.Background(), pubKey, wrapper.WrappedPhase0BeaconBlock(block.Block), [32]byte{2})
require.NoError(t, err, "Expected allowed block not to throw error")
}
func TestPostBlockSignUpdate(t *testing.T) {
config := &features.Flags{
SlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
validator, _, validatorKey, finish := setup(t)
defer finish()
pubKey := [48]byte{}
copy(pubKey[:], validatorKey.PublicKey().Marshal())
emptyBlock := util.NewBeaconBlock()
emptyBlock.Block.Slot = 10
emptyBlock.Block.ProposerIndex = 0
mockProtector := &mockSlasher.MockProtector{AllowBlock: false}
validator.protector = mockProtector
err := validator.postBlockSignUpdate(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(emptyBlock), [32]byte{})
require.ErrorContains(t, failedPostBlockSignErr, err, "Expected error when post signature update is detected as slashable")
mockProtector.AllowBlock = true
err = validator.postBlockSignUpdate(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(emptyBlock), [32]byte{})
m.nodeClient.EXPECT().IsSlashableBlock(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.ProposerSlashingResponse{ProposerSlashings: []*ethpb.ProposerSlashing{{}}}, nil /*err*/)
err := validator.slashableProposalCheck(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{2})
require.ErrorContains(t, failedBlockSignExternalErr, err)
m.slasherClient.EXPECT().IsSlashableBlock(
gomock.Any(), // ctx
gomock.Any(),
).Return(&ethpb.ProposerSlashingResponse{}, nil /*err*/)
err = validator.slashableProposalCheck(context.Background(), pubKey, wrapper.WrappedPhase0SignedBeaconBlock(block), [32]byte{2})
require.NoError(t, err, "Expected allowed block not to throw error")
}

View File

@@ -296,10 +296,10 @@ func TestProposeBlock_BlocksDoubleProposal(t *testing.T) {
).Return(&ethpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil /*error*/)
validator.ProposeBlock(context.Background(), slot, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
validator.ProposeBlock(context.Background(), slot, pubKey)
require.LogsContain(t, hook, failedPreBlockSignLocalErr)
require.LogsContain(t, hook, failedBlockSignLocalErr)
}
func TestProposeBlockAltair_BlocksDoubleProposal(t *testing.T) {
@@ -356,10 +356,10 @@ func TestProposeBlockAltair_BlocksDoubleProposal(t *testing.T) {
).Return(&ethpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil /*error*/)
validator.ProposeBlock(context.Background(), slot, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
validator.ProposeBlock(context.Background(), slot, pubKey)
require.LogsContain(t, hook, failedPreBlockSignLocalErr)
require.LogsContain(t, hook, failedBlockSignLocalErr)
}
func TestProposeBlock_BlocksDoubleProposal_After54KEpochs(t *testing.T) {
@@ -408,10 +408,10 @@ func TestProposeBlock_BlocksDoubleProposal_After54KEpochs(t *testing.T) {
).Return(&ethpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil /*error*/)
validator.ProposeBlock(context.Background(), farFuture, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
validator.ProposeBlock(context.Background(), farFuture, pubKey)
require.LogsContain(t, hook, failedPreBlockSignLocalErr)
require.LogsContain(t, hook, failedBlockSignLocalErr)
}
func TestProposeBlock_AllowsPastProposals(t *testing.T) {
@@ -449,7 +449,7 @@ func TestProposeBlock_AllowsPastProposals(t *testing.T) {
).Times(2).Return(&ethpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil /*error*/)
validator.ProposeBlock(context.Background(), farAhead, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
past := params.BeaconConfig().SlotsPerEpoch.Mul(uint64(params.BeaconConfig().WeakSubjectivityPeriod - 400))
blk2 := util.NewBeaconBlock()
@@ -459,7 +459,7 @@ func TestProposeBlock_AllowsPastProposals(t *testing.T) {
gomock.Any(),
).Return(blk2.Block, nil /*err*/)
validator.ProposeBlock(context.Background(), past, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
}
func TestProposeBlock_AllowsSameEpoch(t *testing.T) {
@@ -497,7 +497,7 @@ func TestProposeBlock_AllowsSameEpoch(t *testing.T) {
).Times(2).Return(&ethpb.ProposeResponse{BlockRoot: make([]byte, 32)}, nil /*error*/)
validator.ProposeBlock(context.Background(), farAhead, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
blk2 := util.NewBeaconBlock()
blk2.Block.Slot = farAhead - 4
@@ -507,7 +507,7 @@ func TestProposeBlock_AllowsSameEpoch(t *testing.T) {
).Return(blk2.Block, nil /*err*/)
validator.ProposeBlock(context.Background(), farAhead-4, pubKey)
require.LogsDoNotContain(t, hook, failedPreBlockSignLocalErr)
require.LogsDoNotContain(t, hook, failedBlockSignLocalErr)
}
func TestProposeBlock_BroadcastsBlock(t *testing.T) {

View File

@@ -9,7 +9,6 @@ import (
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/beacon-chain/core"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/validator/client/iface"
@@ -40,11 +39,6 @@ func run(ctx context.Context, v iface.Validator) {
cleanup()
log.Fatalf("Wallet is not ready: %v", err)
}
if features.Get().SlasherProtection {
if err := v.SlasherReady(ctx); err != nil {
log.Fatalf("Slasher is not ready: %v", err)
}
}
ticker := time.NewTicker(backOffPeriod)
defer ticker.Stop()

View File

@@ -8,7 +8,6 @@ import (
types "github.com/prysmaticlabs/eth2-types"
"github.com/prysmaticlabs/prysm/async/event"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"github.com/prysmaticlabs/prysm/validator/client/iface"
@@ -62,17 +61,6 @@ func TestCancelledContext_WaitsForActivation(t *testing.T) {
assert.Equal(t, 1, v.WaitForActivationCalled, "Expected WaitForActivation() to be called")
}
func TestCancelledContext_ChecksSlasherReady(t *testing.T) {
v := &testutil.FakeValidator{Keymanager: &mockKeymanager{accountsChangedFeed: &event.Feed{}}}
cfg := &features.Flags{
SlasherProtection: true,
}
reset := features.InitWithReset(cfg)
defer reset()
run(cancelledContext(), v)
assert.Equal(t, true, v.SlasherReadyCalled, "Expected SlasherReady() to be called")
}
func TestUpdateDuties_NextSlot(t *testing.T) {
v := &testutil.FakeValidator{Keymanager: &mockKeymanager{accountsChangedFeed: &event.Feed{}}}
ctx, cancel := context.WithCancel(context.Background())

View File

@@ -27,7 +27,6 @@ import (
"github.com/prysmaticlabs/prysm/validator/graffiti"
"github.com/prysmaticlabs/prysm/validator/keymanager"
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
slashingiface "github.com/prysmaticlabs/prysm/validator/slashing-protection/iface"
"go.opencensus.io/plugin/ocgrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@@ -64,7 +63,6 @@ type ValidatorService struct {
withCert string
endpoint string
validator iface.Validator
protector slashingiface.Protector
ctx context.Context
keyManager keymanager.IKeymanager
grpcHeaders []string
@@ -82,7 +80,6 @@ type Config struct {
GrpcRetriesFlag uint
GrpcRetryDelay time.Duration
GrpcMaxCallRecvMsgSizeFlag int
Protector slashingiface.Protector
Endpoint string
Validator iface.Validator
ValDB db.Database
@@ -112,7 +109,6 @@ func NewValidatorService(ctx context.Context, cfg *Config) (*ValidatorService, e
grpcRetries: cfg.GrpcRetriesFlag,
grpcRetryDelay: cfg.GrpcRetryDelay,
grpcHeaders: strings.Split(cfg.GrpcHeadersFlag, ","),
protector: cfg.Protector,
validator: cfg.Validator,
db: cfg.ValDB,
walletInitializedFeed: cfg.WalletInitializedFeed,
@@ -188,7 +184,6 @@ func (v *ValidatorService) Start() {
attLogs: make(map[[32]byte]*attSubmitted),
domainDataCache: cache,
aggregatedSlotCommitteeIDCache: aggregatedSlotCommitteeIDCache,
protector: v.protector,
voteStats: voteStats{startEpoch: types.Epoch(^uint64(0))},
useWeb: v.useWeb,
walletInitializedFeed: v.walletInitializedFeed,

View File

@@ -9,7 +9,6 @@ import (
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/prysmaticlabs/prysm/config/features"
"github.com/prysmaticlabs/prysm/io/file"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper"
@@ -76,12 +75,6 @@ func setupEIP3076SpecTests(t *testing.T) []*eip3076TestCase {
}
func TestEIP3076SpecTests(t *testing.T) {
config := &features.Flags{
SlasherProtection: true,
}
reset := features.InitWithReset(config)
defer reset()
testCases := setupEIP3076SpecTests(t)
for _, tt := range testCases {
t.Run(tt.Name, func(t *testing.T) {
@@ -130,22 +123,12 @@ func TestEIP3076SpecTests(t *testing.T) {
copy(signingRoot[:], signingRootBytes)
}
err = validator.preBlockSignValidations(context.Background(), pk, wrapper.WrappedPhase0BeaconBlock(b.Block), signingRoot)
err = validator.slashableProposalCheck(context.Background(), pk, wrapper.WrappedPhase0SignedBeaconBlock(b), signingRoot)
if sb.ShouldSucceed {
require.NoError(t, err)
} else {
require.NotEqual(t, nil, err, "pre validation should have failed for block")
}
// Only proceed post update if pre validation did not error.
if err == nil {
err = validator.postBlockSignUpdate(context.Background(), pk, wrapper.WrappedPhase0SignedBeaconBlock(b), signingRoot)
if sb.ShouldSucceed {
require.NoError(t, err)
} else {
require.NotEqual(t, nil, err, "post validation should have failed for block")
}
}
}
// This loops through a list of attestation signings to attempt after importing the interchange data above.

View File

@@ -36,20 +36,17 @@ import (
"github.com/prysmaticlabs/prysm/validator/db/kv"
"github.com/prysmaticlabs/prysm/validator/graffiti"
"github.com/prysmaticlabs/prysm/validator/keymanager"
slashingiface "github.com/prysmaticlabs/prysm/validator/slashing-protection/iface"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/emptypb"
)
// reconnectPeriod is the frequency that we try to restart our
// slasher connection when the slasher client connection is not ready.
var reconnectPeriod = 5 * time.Second
// keyFetchPeriod is the frequency that we try to refetch validating keys
// in case no keys were fetched previously.
var keyRefetchPeriod = 30 * time.Second
var (
keyRefetchPeriod = 30 * time.Second
)
var (
msgCouldNotFetchKeys = "could not fetch validating keys"
@@ -81,7 +78,7 @@ type validator struct {
keyManager keymanager.IKeymanager
beaconClient ethpb.BeaconChainClient
validatorClient ethpb.BeaconNodeValidatorClient
protector slashingiface.Protector
slashingProtectionClient ethpb.SlasherClient
db vdb.Database
graffiti []byte
voteStats voteStats
@@ -224,12 +221,14 @@ func (v *validator) WaitForSync(ctx context.Context) error {
}
}
<<<<<<< HEAD
=======
// SlasherReady checks if slasher that was configured as external protection
// is reachable.
func (v *validator) SlasherReady(ctx context.Context) error {
ctx, span := trace.StartSpan(ctx, "validator.SlasherReady")
defer span.End()
if features.Get().SlasherProtection {
if features.Get().RemoteSlasherProtection {
err := v.protector.Status()
if err == nil {
return nil
@@ -255,6 +254,7 @@ func (v *validator) SlasherReady(ctx context.Context) error {
return nil
}
>>>>>>> develop
// ReceiveBlocks starts a gRPC client stream listener to obtain
// blocks from the beacon node. Upon receiving a block, the service
// broadcasts it to a feed for other usages to subscribe to.

View File

@@ -39,7 +39,7 @@ func TestPruneAttestations_NoPruning(t *testing.T) {
}
func TestPruneAttestations_OK(t *testing.T) {
numKeys := uint64(2048)
numKeys := uint64(64)
pks := make([][48]byte, 0, numKeys)
for i := uint64(0); i < numKeys; i++ {
pks = append(pks, bytesutil.ToBytes48(bytesutil.ToBytes(i, 48)))

View File

@@ -52,8 +52,6 @@ go_library(
"//validator/keymanager:go_default_library",
"//validator/keymanager/imported:go_default_library",
"//validator/rpc:go_default_library",
"//validator/slashing-protection:go_default_library",
"//validator/slashing-protection/iface:go_default_library",
"//validator/web:go_default_library",
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library",
"@com_github_pkg_errors//:go_default_library",

View File

@@ -40,8 +40,6 @@ import (
"github.com/prysmaticlabs/prysm/validator/keymanager"
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
"github.com/prysmaticlabs/prysm/validator/rpc"
slashingprotection "github.com/prysmaticlabs/prysm/validator/slashing-protection"
"github.com/prysmaticlabs/prysm/validator/slashing-protection/iface"
"github.com/prysmaticlabs/prysm/validator/web"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
@@ -251,11 +249,6 @@ func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
return err
}
}
if features.Get().SlasherProtection {
if err := c.registerSlasherService(); err != nil {
return err
}
}
if err := c.registerValidatorService(keyManager); err != nil {
return err
}
@@ -340,11 +333,6 @@ func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
return err
}
}
if features.Get().SlasherProtection {
if err := c.registerSlasherService(); err != nil {
return err
}
}
if err := c.registerValidatorService(keyManager); err != nil {
return err
}
@@ -395,12 +383,6 @@ func (c *ValidatorClient) registerValidatorService(
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
var sp *slashingprotection.Service
var protector iface.Protector
if err := c.services.FetchService(&sp); err == nil {
protector = sp
}
gStruct := &g.Graffiti{}
var err error
if c.cliCtx.IsSet(flags.GraffitiFileFlag.Name) {
@@ -423,7 +405,6 @@ func (c *ValidatorClient) registerValidatorService(
GrpcRetriesFlag: grpcRetries,
GrpcRetryDelay: grpcRetryDelay,
GrpcHeadersFlag: c.cliCtx.String(flags.GrpcHeadersFlag.Name),
Protector: protector,
ValDB: c.db,
UseWeb: c.cliCtx.Bool(flags.EnableWebFlag.Name),
WalletInitializedFeed: c.walletInitialized,
@@ -436,29 +417,6 @@ func (c *ValidatorClient) registerValidatorService(
return c.services.RegisterService(v)
}
func (c *ValidatorClient) registerSlasherService() error {
endpoint := c.cliCtx.String(flags.SlasherRPCProviderFlag.Name)
if endpoint == "" {
return errors.New("external slasher feature flag is set but no slasher endpoint is configured")
}
cert := c.cliCtx.String(flags.SlasherCertFlag.Name)
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
sp, err := slashingprotection.NewService(c.cliCtx.Context, &slashingprotection.Config{
Endpoint: endpoint,
CertFlag: cert,
GrpcMaxCallRecvMsgSizeFlag: maxCallRecvMsgSize,
GrpcRetriesFlag: grpcRetries,
GrpcRetryDelay: grpcRetryDelay,
GrpcHeadersFlag: c.cliCtx.String(flags.GrpcHeadersFlag.Name),
})
if err != nil {
return errors.Wrap(err, "could not initialize slasher service")
}
return c.services.RegisterService(sp)
}
func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.IKeymanager) error {
var vs *client.ValidatorService

View File

@@ -5,9 +5,7 @@ go_library(
srcs = [
"cli_export.go",
"cli_import.go",
"external.go",
"log.go",
"slasher_client.go",
],
importpath = "github.com/prysmaticlabs/prysm/validator/slashing-protection",
visibility = [
@@ -15,42 +13,28 @@ go_library(
"//validator:__subpackages__",
],
deps = [
"//api/grpc:go_default_library",
"//cmd:go_default_library",
"//cmd/validator/flags:go_default_library",
"//io/file:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//validator/accounts/userprompt:go_default_library",
"//validator/db/kv:go_default_library",
"//validator/slashing-protection/local/standard-protection-format:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//retry:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//tracing/opentracing:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
"@io_opencensus_go//plugin/ocgrpc:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//connectivity:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"cli_import_export_test.go",
"external_test.go",
"slasher_client_test.go",
],
srcs = ["cli_import_export_test.go"],
embed = [":go_default_library"],
deps = [
"//cmd:go_default_library",
"//cmd/validator/flags:go_default_library",
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//io/file:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//validator/db/kv:go_default_library",
@@ -58,6 +42,5 @@ go_test(
"//validator/slashing-protection/local/standard-protection-format/format:go_default_library",
"//validator/testing:go_default_library",
"@com_github_urfave_cli_v2//:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
],
)

View File

@@ -1,65 +0,0 @@
package slashingprotection
import (
"context"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// CheckBlockSafety this function is part of slashing protection for block proposals it performs
// validation without db update. To be used before the block is signed.
func (s *Service) CheckBlockSafety(ctx context.Context, blockHeader *ethpb.BeaconBlockHeader) bool {
slashable, err := s.slasherClient.IsSlashableBlockNoUpdate(ctx, blockHeader)
if err != nil {
log.Errorf("External slashing block protection returned an error: %v", err)
return false
}
if slashable != nil && slashable.Slashable {
log.Warn("External slashing proposal protection found the block to be slashable")
}
return !slashable.Slashable
}
// CommitBlock this function is part of slashing protection for block proposals it performs
// validation and db update. To be used after the block is proposed.
func (s *Service) CommitBlock(ctx context.Context, blockHeader *ethpb.SignedBeaconBlockHeader) (bool, error) {
ps, err := s.slasherClient.IsSlashableBlock(ctx, blockHeader)
if err != nil {
log.Errorf("External slashing block protection returned an error: %v", err)
return false, err
}
if ps != nil && len(ps.ProposerSlashings) != 0 {
log.Warn("External slashing proposal protection found the block to be slashable")
return false, nil
}
return true, nil
}
// CheckAttestationSafety implements the slashing protection for attestations without db update.
// To be used before signing.
func (s *Service) CheckAttestationSafety(ctx context.Context, attestation *ethpb.IndexedAttestation) bool {
slashable, err := s.slasherClient.IsSlashableAttestationNoUpdate(ctx, attestation)
if err != nil {
log.Errorf("External slashing attestation protection returned an error: %v", err)
return false
}
if slashable.Slashable {
log.Warn("External slashing attestation protection found the attestation to be slashable")
}
return !slashable.Slashable
}
// CommitAttestation implements the slashing protection for attestations it performs
// validation and db update. To be used after the attestation is proposed.
func (s *Service) CommitAttestation(ctx context.Context, attestation *ethpb.IndexedAttestation) bool {
as, err := s.slasherClient.IsSlashableAttestation(ctx, attestation)
if err != nil {
log.Errorf("External slashing attestation protection returned an error: %v", err)
return false
}
if as != nil && len(as.AttesterSlashings) != 0 {
log.Warnf("External slashing attestation protection found the attestation to be slashable: %v", as)
return false
}
return true
}

View File

@@ -1,91 +0,0 @@
package slashingprotection
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/testing/assert"
mockSlasher "github.com/prysmaticlabs/prysm/validator/testing"
)
func TestService_VerifyAttestation(t *testing.T) {
s := &Service{slasherClient: mockSlasher.MockSlasher{SlashAttestation: true}}
att := &eth.IndexedAttestation{
AttestingIndices: []uint64{1, 2},
Data: &eth.AttestationData{
Slot: 5,
CommitteeIndex: 2,
BeaconBlockRoot: []byte("great block"),
Source: &eth.Checkpoint{
Epoch: 4,
Root: []byte("good source"),
},
Target: &eth.Checkpoint{
Epoch: 10,
Root: []byte("good target"),
},
},
}
assert.Equal(t, false, s.CheckAttestationSafety(context.Background(), att), "Expected verify attestation to fail verification")
s = &Service{slasherClient: mockSlasher.MockSlasher{SlashAttestation: false}}
assert.Equal(t, true, s.CheckAttestationSafety(context.Background(), att), "Expected verify attestation to pass verification")
}
func TestService_CommitAttestation(t *testing.T) {
s := &Service{slasherClient: mockSlasher.MockSlasher{SlashAttestation: true}}
att := &eth.IndexedAttestation{
AttestingIndices: []uint64{1, 2},
Data: &eth.AttestationData{
Slot: 5,
CommitteeIndex: 2,
BeaconBlockRoot: []byte("great block"),
Source: &eth.Checkpoint{
Epoch: 4,
Root: []byte("good source"),
},
Target: &eth.Checkpoint{
Epoch: 10,
Root: []byte("good target"),
},
},
}
assert.Equal(t, false, s.CommitAttestation(context.Background(), att), "Expected commit attestation to fail verification")
s = &Service{slasherClient: mockSlasher.MockSlasher{SlashAttestation: false}}
assert.Equal(t, true, s.CommitAttestation(context.Background(), att), "Expected commit attestation to pass verification")
}
func TestService_CommitBlock(t *testing.T) {
s := &Service{slasherClient: mockSlasher.MockSlasher{SlashBlock: true}}
blk := &eth.SignedBeaconBlockHeader{
Header: &eth.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 0,
ParentRoot: bytesutil.PadTo([]byte("parent"), 32),
StateRoot: bytesutil.PadTo([]byte("state"), 32),
BodyRoot: bytesutil.PadTo([]byte("body"), 32),
},
}
slashable, err := s.CommitBlock(context.Background(), blk)
assert.NoError(t, err)
assert.Equal(t, false, slashable, "Expected commit block to fail verification")
s = &Service{slasherClient: mockSlasher.MockSlasher{SlashBlock: false}}
slashable, err = s.CommitBlock(context.Background(), blk)
assert.NoError(t, err)
assert.Equal(t, true, slashable, "Expected commit block to pass verification")
}
func TestService_VerifyBlock(t *testing.T) {
s := &Service{slasherClient: mockSlasher.MockSlasher{SlashBlock: true}}
blk := &eth.BeaconBlockHeader{
Slot: 0,
ProposerIndex: 0,
ParentRoot: bytesutil.PadTo([]byte("parent"), 32),
StateRoot: bytesutil.PadTo([]byte("state"), 32),
BodyRoot: bytesutil.PadTo([]byte("body"), 32),
}
assert.Equal(t, false, s.CheckBlockSafety(context.Background(), blk), "Expected verify block to fail verification")
s = &Service{slasherClient: mockSlasher.MockSlasher{SlashBlock: false}}
assert.Equal(t, true, s.CheckBlockSafety(context.Background(), blk), "Expected verify block to pass verification")
}

View File

@@ -1,9 +0,0 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["protector.go"],
importpath = "github.com/prysmaticlabs/prysm/validator/slashing-protection/iface",
visibility = ["//validator:__subpackages__"],
deps = ["//proto/prysm/v1alpha1:go_default_library"],
)

View File

@@ -1,16 +0,0 @@
package iface
import (
"context"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
)
// Protector interface defines the methods of the service that provides slashing protection.
type Protector interface {
CheckAttestationSafety(ctx context.Context, attestation *eth.IndexedAttestation) bool
CommitAttestation(ctx context.Context, attestation *eth.IndexedAttestation) bool
CheckBlockSafety(ctx context.Context, blockHeader *eth.BeaconBlockHeader) bool
CommitBlock(ctx context.Context, blockHeader *eth.SignedBeaconBlockHeader) (bool, error)
Status() error
}

View File

@@ -1,129 +0,0 @@
package slashingprotection
import (
"context"
"errors"
"fmt"
"strings"
"time"
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
grpcutil "github.com/prysmaticlabs/prysm/api/grpc"
ethsl "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"go.opencensus.io/plugin/ocgrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/connectivity"
"google.golang.org/grpc/credentials"
)
// Service represents a service to manage the validator
// ￿slashing protection.
type Service struct {
cfg *Config
ctx context.Context
cancel context.CancelFunc
conn *grpc.ClientConn
grpcHeaders []string
slasherClient ethsl.SlasherClient
}
// Config for the validator service.
type Config struct {
Endpoint string
CertFlag string
GrpcMaxCallRecvMsgSizeFlag int
GrpcRetriesFlag uint
GrpcRetryDelay time.Duration
GrpcHeadersFlag string
}
// NewService creates a new validator service for the service
// registry.
func NewService(ctx context.Context, cfg *Config) (*Service, error) {
ctx, cancel := context.WithCancel(ctx)
return &Service{
cfg: cfg,
ctx: ctx,
cancel: cancel,
grpcHeaders: strings.Split(cfg.GrpcHeadersFlag, ","),
}, nil
}
// Start the slasher protection service and grpc client.
func (s *Service) Start() {
if s.cfg.Endpoint != "" {
s.slasherClient = s.startSlasherClient()
}
}
func (s *Service) startSlasherClient() ethsl.SlasherClient {
var dialOpt grpc.DialOption
if s.cfg.CertFlag != "" {
creds, err := credentials.NewClientTLSFromFile(s.cfg.CertFlag, "")
if err != nil {
log.Errorf("Could not get valid slasher credentials: %v", err)
return nil
}
dialOpt = grpc.WithTransportCredentials(creds)
} else {
dialOpt = grpc.WithInsecure()
log.Warn("You are using an insecure slasher gRPC connection! Please provide a certificate and key to use a secure connection.")
}
s.ctx = grpcutil.AppendHeaders(s.ctx, s.grpcHeaders)
opts := []grpc.DialOption{
dialOpt,
grpc.WithDefaultCallOptions(
grpc_retry.WithMax(s.cfg.GrpcRetriesFlag),
grpc_retry.WithBackoff(grpc_retry.BackoffLinear(s.cfg.GrpcRetryDelay)),
),
grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
grpc.WithStreamInterceptor(middleware.ChainStreamClient(
grpc_opentracing.StreamClientInterceptor(),
grpc_prometheus.StreamClientInterceptor,
grpc_retry.StreamClientInterceptor(),
)),
grpc.WithUnaryInterceptor(middleware.ChainUnaryClient(
grpc_opentracing.UnaryClientInterceptor(),
grpc_prometheus.UnaryClientInterceptor,
grpc_retry.UnaryClientInterceptor(),
grpcutil.LogRequests,
)),
}
conn, err := grpc.DialContext(s.ctx, s.cfg.Endpoint, opts...)
if err != nil {
log.Errorf("Could not dial slasher endpoint: %s, %v", s.cfg.Endpoint, err)
return nil
}
log.Debug("Successfully started slasher gRPC connection")
s.conn = conn
return ethsl.NewSlasherClient(s.conn)
}
// Stop the validator service.
func (s *Service) Stop() error {
s.cancel()
log.Info("Stopping slashing protection service")
if s.conn != nil {
return s.conn.Close()
}
return nil
}
// Status checks if the connection to slasher server is ready,
// returns error otherwise.
func (s *Service) Status() error {
if s.conn == nil {
return errors.New("no connection to slasher RPC")
}
if s.conn.GetState() != connectivity.Ready {
return fmt.Errorf("can`t connect to slasher server at: %v connection status: %v ", s.cfg.Endpoint, s.conn.GetState())
}
return nil
}

View File

@@ -1,23 +0,0 @@
package slashingprotection
import (
"context"
"testing"
"github.com/prysmaticlabs/prysm/testing/assert"
"github.com/prysmaticlabs/prysm/testing/require"
"google.golang.org/grpc/metadata"
)
func TestGrpcHeaders(t *testing.T) {
s := &Service{
cfg: &Config{},
ctx: context.Background(),
grpcHeaders: []string{"first=value1", "second=value2"},
}
s.startSlasherClient()
md, _ := metadata.FromOutgoingContext(s.ctx)
require.Equal(t, 2, md.Len(), "MetadataV0 contains wrong number of values")
assert.Equal(t, "value1", md.Get("first")[0])
assert.Equal(t, "value2", md.Get("second")[0])
}

View File

@@ -11,9 +11,7 @@ type MockProtector struct {
AllowAttestation bool
AllowBlock bool
VerifyAttestationCalled bool
CommitAttestationCalled bool
VerifyBlockCalled bool
CommitBlockCalled bool
StatusCalled bool
}
@@ -23,24 +21,12 @@ func (mp MockProtector) CheckAttestationSafety(_ context.Context, _ *eth.Indexed
return mp.AllowAttestation
}
// CommitAttestation returns bool with allow attestation value.
func (mp MockProtector) CommitAttestation(_ context.Context, _ *eth.IndexedAttestation) bool {
mp.CommitAttestationCalled = true
return mp.AllowAttestation
}
// CheckBlockSafety returns bool with allow block value.
func (mp MockProtector) CheckBlockSafety(_ context.Context, _ *eth.BeaconBlockHeader) bool {
func (mp MockProtector) CheckBlockSafety(_ context.Context, _ *eth.SignedBeaconBlockHeader) bool {
mp.VerifyBlockCalled = true
return mp.AllowBlock
}
// CommitBlock returns bool with allow block value.
func (mp MockProtector) CommitBlock(_ context.Context, _ *eth.SignedBeaconBlockHeader) (bool, error) {
mp.CommitBlockCalled = true
return mp.AllowBlock, nil
}
// Status returns nil.
func (mp MockProtector) Status() error {
mp.StatusCalled = true

View File

@@ -5,30 +5,27 @@ import (
"errors"
eth "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
slashpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
)
// MockSlasher mocks the slasher rpc server.
type MockSlasher struct {
SlashAttestation bool
SlashBlock bool
IsSlashableAttestationCalled bool
IsSlashableAttestationNoUpdateCalled bool
IsSlashableBlockCalled bool
IsSlashableBlockNoUpdateCalled bool
SlashAttestation bool
SlashBlock bool
IsSlashableAttestationCalled bool
IsSlashableBlockCalled bool
}
// HighestAttestations will return an empty array of attestations.
func (ms MockSlasher) HighestAttestations(ctx context.Context, req *slashpb.HighestAttestationRequest, _ ...grpc.CallOption) (*slashpb.HighestAttestationResponse, error) {
return &slashpb.HighestAttestationResponse{
func (_ MockSlasher) HighestAttestations(ctx context.Context, req *eth.HighestAttestationRequest, _ ...grpc.CallOption) (*eth.HighestAttestationResponse, error) {
return &eth.HighestAttestationResponse{
Attestations: nil,
}, nil
}
// IsSlashableAttestation returns slashbale attestation if slash attestation is set to true.
func (ms MockSlasher) IsSlashableAttestation(_ context.Context, in *eth.IndexedAttestation, _ ...grpc.CallOption) (*slashpb.AttesterSlashingResponse, error) {
func (ms MockSlasher) IsSlashableAttestation(_ context.Context, in *eth.IndexedAttestation, _ ...grpc.CallOption) (*eth.AttesterSlashingResponse, error) {
ms.IsSlashableAttestationCalled = true
if ms.SlashAttestation {
@@ -42,24 +39,15 @@ func (ms MockSlasher) IsSlashableAttestation(_ context.Context, in *eth.IndexedA
Attestation_2: slashingAtt,
},
}
return &slashpb.AttesterSlashingResponse{
return &eth.AttesterSlashingResponse{
AttesterSlashings: slashings,
}, nil
}
return nil, nil
}
// IsSlashableAttestationNoUpdate returns slashbale if slash attestation is set to true.
func (ms MockSlasher) IsSlashableAttestationNoUpdate(_ context.Context, _ *eth.IndexedAttestation, _ ...grpc.CallOption) (*slashpb.Slashable, error) {
ms.IsSlashableAttestationNoUpdateCalled = true
return &slashpb.Slashable{
Slashable: ms.SlashAttestation,
}, nil
}
// IsSlashableBlock returns proposer slashing if slash block is set to true.
func (ms MockSlasher) IsSlashableBlock(_ context.Context, in *eth.SignedBeaconBlockHeader, _ ...grpc.CallOption) (*slashpb.ProposerSlashingResponse, error) {
func (ms MockSlasher) IsSlashableBlock(_ context.Context, in *eth.SignedBeaconBlockHeader, _ ...grpc.CallOption) (*eth.ProposerSlashingResponse, error) {
ms.IsSlashableBlockCalled = true
if ms.SlashBlock {
slashingBlk, ok := proto.Clone(in).(*eth.SignedBeaconBlockHeader)
@@ -72,17 +60,9 @@ func (ms MockSlasher) IsSlashableBlock(_ context.Context, in *eth.SignedBeaconBl
Header_2: slashingBlk,
},
}
return &slashpb.ProposerSlashingResponse{
return &eth.ProposerSlashingResponse{
ProposerSlashings: slashings,
}, nil
}
return nil, nil
}
// IsSlashableBlockNoUpdate returns slashbale if slash block is set to true.
func (ms MockSlasher) IsSlashableBlockNoUpdate(_ context.Context, _ *eth.BeaconBlockHeader, _ ...grpc.CallOption) (*slashpb.Slashable, error) {
ms.IsSlashableBlockNoUpdateCalled = true
return &slashpb.Slashable{
Slashable: ms.SlashBlock,
}, nil
}