Slasher grpc service (#3271)

This commit is contained in:
shayzluf
2019-09-26 21:59:10 +05:30
committed by terence tsao
parent a683f4652f
commit 8f0b131631
14 changed files with 908 additions and 114 deletions

6
.gitignore vendored
View File

@@ -21,4 +21,8 @@ yarn-error.log
.vscode/
# Ignore password file
password.txt
password.txt
# go dependancy
/go.mod
/go.sum

View File

@@ -17,6 +17,7 @@ go_library(
visibility = [
"//beacon-chain:__subpackages__",
"//shared/testutil:__pkg__",
"//slasher:__subpackages__",
],
deps = [
"//beacon-chain/cache:go_default_library",

View File

@@ -6,6 +6,7 @@ package eth
import (
context "context"
fmt "fmt"
io "io"
math "math"
proto "github.com/gogo/protobuf/proto"
@@ -24,29 +25,143 @@ var _ = math.Inf
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type ProposerSlashingRequest struct {
BlockHeader *BeaconBlockHeader `protobuf:"bytes,1,opt,name=block_header,json=blockHeader,proto3" json:"block_header,omitempty"`
ValidatorIndex uint64 `protobuf:"varint,2,opt,name=validator_index,json=validatorIndex,proto3" json:"validator_index,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ProposerSlashingRequest) Reset() { *m = ProposerSlashingRequest{} }
func (m *ProposerSlashingRequest) String() string { return proto.CompactTextString(m) }
func (*ProposerSlashingRequest) ProtoMessage() {}
func (*ProposerSlashingRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_c3db2cc39857595b, []int{0}
}
func (m *ProposerSlashingRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ProposerSlashingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ProposerSlashingRequest.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ProposerSlashingRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_ProposerSlashingRequest.Merge(m, src)
}
func (m *ProposerSlashingRequest) XXX_Size() int {
return m.Size()
}
func (m *ProposerSlashingRequest) XXX_DiscardUnknown() {
xxx_messageInfo_ProposerSlashingRequest.DiscardUnknown(m)
}
var xxx_messageInfo_ProposerSlashingRequest proto.InternalMessageInfo
func (m *ProposerSlashingRequest) GetBlockHeader() *BeaconBlockHeader {
if m != nil {
return m.BlockHeader
}
return nil
}
func (m *ProposerSlashingRequest) GetValidatorIndex() uint64 {
if m != nil {
return m.ValidatorIndex
}
return 0
}
type ProposerSlashingResponse struct {
ProposerSlashing []*ProposerSlashing `protobuf:"bytes,1,rep,name=proposer_slashing,json=proposerSlashing,proto3" json:"proposer_slashing,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ProposerSlashingResponse) Reset() { *m = ProposerSlashingResponse{} }
func (m *ProposerSlashingResponse) String() string { return proto.CompactTextString(m) }
func (*ProposerSlashingResponse) ProtoMessage() {}
func (*ProposerSlashingResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_c3db2cc39857595b, []int{1}
}
func (m *ProposerSlashingResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ProposerSlashingResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ProposerSlashingResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ProposerSlashingResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_ProposerSlashingResponse.Merge(m, src)
}
func (m *ProposerSlashingResponse) XXX_Size() int {
return m.Size()
}
func (m *ProposerSlashingResponse) XXX_DiscardUnknown() {
xxx_messageInfo_ProposerSlashingResponse.DiscardUnknown(m)
}
var xxx_messageInfo_ProposerSlashingResponse proto.InternalMessageInfo
func (m *ProposerSlashingResponse) GetProposerSlashing() []*ProposerSlashing {
if m != nil {
return m.ProposerSlashing
}
return nil
}
func init() {
proto.RegisterType((*ProposerSlashingRequest)(nil), "ethereum.eth.v1alpha1.ProposerSlashingRequest")
proto.RegisterType((*ProposerSlashingResponse)(nil), "ethereum.eth.v1alpha1.ProposerSlashingResponse")
}
func init() { proto.RegisterFile("proto/eth/v1alpha1/slasher.proto", fileDescriptor_c3db2cc39857595b) }
var fileDescriptor_c3db2cc39857595b = []byte{
// 296 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xc1, 0x4a, 0xf4, 0x30,
0x14, 0x85, 0x29, 0x3f, 0xfc, 0x42, 0x56, 0x12, 0x98, 0x59, 0x8c, 0x50, 0x44, 0x14, 0x5d, 0x25,
0x33, 0x8a, 0x2b, 0x57, 0x56, 0x04, 0xdd, 0x09, 0x2e, 0x84, 0xd9, 0xc8, 0x4d, 0xbd, 0x36, 0xc5,
0xb4, 0x29, 0xc9, 0xad, 0x30, 0xef, 0xe0, 0x83, 0xb9, 0xf4, 0x11, 0xa4, 0x4f, 0x22, 0x93, 0x38,
0x5a, 0xb4, 0x23, 0xba, 0xbc, 0xbd, 0xdf, 0x3d, 0xe7, 0xf4, 0x84, 0x6d, 0x37, 0xce, 0x92, 0x95,
0x48, 0x5a, 0x3e, 0xce, 0xc0, 0x34, 0x1a, 0x66, 0xd2, 0x1b, 0xf0, 0x1a, 0x9d, 0x08, 0x2b, 0x3e,
0x42, 0xd2, 0xe8, 0xb0, 0xad, 0x04, 0x92, 0x16, 0x2b, 0x68, 0xb2, 0x55, 0x58, 0x5b, 0x18, 0x94,
0x01, 0x52, 0xed, 0xbd, 0xc4, 0xaa, 0xa1, 0x45, 0xbc, 0x99, 0xec, 0x0d, 0xa8, 0x2a, 0x84, 0xdc,
0xd6, 0xb7, 0xca, 0xd8, 0xfc, 0xe1, 0x1d, 0xdb, 0x1d, 0xc0, 0x80, 0x08, 0x3d, 0x01, 0x95, 0xb6,
0x8e, 0xd4, 0xe1, 0xd3, 0x3f, 0xb6, 0x71, 0x1d, 0x23, 0x71, 0x64, 0xe3, 0x4b, 0x1f, 0x06, 0x50,
0x06, 0x4f, 0x3f, 0x59, 0xbe, 0x23, 0x06, 0x73, 0x8a, 0x1e, 0x33, 0xd9, 0xff, 0x91, 0x41, 0x17,
0x84, 0xcb, 0xba, 0xe0, 0xc8, 0x36, 0x7b, 0x36, 0xd9, 0x32, 0x32, 0x3f, 0x58, 0x73, 0x9c, 0x85,
0xff, 0x0a, 0xcc, 0x05, 0xc2, 0x1d, 0xba, 0xb5, 0x36, 0x57, 0xce, 0x36, 0xd6, 0xf7, 0x6c, 0x6e,
0x18, 0xff, 0x30, 0x89, 0x4b, 0x30, 0x9e, 0x8f, 0x45, 0xac, 0x56, 0xac, 0xaa, 0x15, 0xe7, 0xcb,
0x6a, 0x7f, 0x2d, 0x3b, 0x4d, 0xf8, 0x9c, 0x8d, 0x86, 0x4a, 0xfa, 0xbb, 0xf6, 0xd7, 0x66, 0xa6,
0x49, 0x76, 0xf6, 0xdc, 0xa5, 0xc9, 0x4b, 0x97, 0x26, 0xaf, 0x5d, 0x9a, 0xcc, 0x8f, 0x8b, 0x92,
0x74, 0xab, 0x44, 0x6e, 0x2b, 0xd9, 0xb8, 0x85, 0xaf, 0x80, 0xca, 0xdc, 0x80, 0xf2, 0x71, 0x92,
0xdf, 0x5f, 0xf8, 0x04, 0x49, 0xab, 0xff, 0xe1, 0xfb, 0xd1, 0x5b, 0x00, 0x00, 0x00, 0xff, 0xff,
0xcd, 0x19, 0xa4, 0x22, 0x7f, 0x02, 0x00, 0x00,
// 406 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0x41, 0x6b, 0x14, 0x31,
0x14, 0xc7, 0x89, 0x15, 0x85, 0xac, 0x68, 0x0d, 0xb4, 0x0e, 0x23, 0x2c, 0xc3, 0xa2, 0xec, 0x9c,
0x92, 0x76, 0xc5, 0x93, 0x27, 0x57, 0x04, 0x8b, 0x17, 0xd9, 0x0a, 0x42, 0x2f, 0x43, 0x32, 0xfb,
0x9c, 0x0c, 0x66, 0x26, 0x31, 0xc9, 0x14, 0xfb, 0x29, 0xbc, 0xfb, 0x89, 0x3c, 0xfa, 0x11, 0x64,
0x3f, 0x89, 0x4c, 0x66, 0xda, 0x2d, 0xbb, 0xb3, 0xb2, 0x3d, 0xbe, 0xf7, 0x7e, 0x79, 0xef, 0x9f,
0xff, 0x7b, 0x38, 0x31, 0x56, 0x7b, 0xcd, 0xc0, 0x4b, 0x76, 0x79, 0xca, 0x95, 0x91, 0xfc, 0x94,
0x39, 0xc5, 0x9d, 0x04, 0x4b, 0x43, 0x89, 0x1c, 0x81, 0x97, 0x60, 0xa1, 0xa9, 0x28, 0x78, 0x49,
0xaf, 0xa1, 0xf8, 0x79, 0xa1, 0x75, 0xa1, 0x80, 0x05, 0x48, 0x34, 0x5f, 0x19, 0x54, 0xc6, 0x5f,
0x75, 0x6f, 0xe2, 0x97, 0x03, 0x5d, 0x05, 0xf0, 0x5c, 0xd7, 0x99, 0x50, 0x3a, 0xff, 0xd6, 0x63,
0x2f, 0x06, 0x30, 0xee, 0x3d, 0x38, 0xcf, 0x7d, 0xa9, 0xeb, 0x8e, 0x9a, 0xfc, 0x44, 0xf8, 0xd9,
0x27, 0xab, 0x8d, 0x76, 0x60, 0xcf, 0x5b, 0x69, 0x65, 0x5d, 0x2c, 0xe0, 0x7b, 0x03, 0xce, 0x93,
0x8f, 0xf8, 0x51, 0x68, 0x98, 0x49, 0xe0, 0x4b, 0xb0, 0x11, 0x4a, 0x50, 0x3a, 0x9a, 0xa5, 0x74,
0x50, 0x33, 0x9d, 0x07, 0x09, 0xf3, 0xf6, 0xc1, 0x87, 0xc0, 0x2f, 0x46, 0x62, 0x1d, 0x90, 0x29,
0x7e, 0x72, 0xc9, 0x55, 0xb9, 0xe4, 0x5e, 0xdb, 0xac, 0xac, 0x97, 0xf0, 0x23, 0xba, 0x97, 0xa0,
0xf4, 0xfe, 0xe2, 0xf1, 0x4d, 0xfa, 0xac, 0xcd, 0x4e, 0x0c, 0x8e, 0xb6, 0x05, 0x39, 0xa3, 0x6b,
0x07, 0xe4, 0x33, 0x7e, 0x6a, 0xfa, 0x5a, 0xe6, 0xfa, 0x62, 0x84, 0x92, 0x83, 0x74, 0x34, 0x9b,
0xee, 0x90, 0xb5, 0xd5, 0xeb, 0xd0, 0x6c, 0x64, 0x66, 0xbf, 0x0e, 0xf0, 0xc3, 0xf3, 0x6e, 0x2d,
0x04, 0xf0, 0xf1, 0x99, 0x0b, 0x01, 0x17, 0x0a, 0xde, 0xae, 0xfd, 0x22, 0x93, 0x1d, 0x03, 0x6e,
0x31, 0xf1, 0xf4, 0xbf, 0xcc, 0x7a, 0x24, 0x71, 0xf8, 0xf0, 0xd6, 0x98, 0x60, 0x1a, 0xa1, 0xfb,
0xfe, 0xa0, 0x5b, 0x4f, 0xcc, 0xf6, 0xe6, 0x7b, 0xf7, 0xbe, 0x60, 0x72, 0x33, 0xb2, 0x83, 0xb8,
0x72, 0xe4, 0x98, 0x76, 0xc7, 0x46, 0xaf, 0x8f, 0x8d, 0xbe, 0x6f, 0x8f, 0x2d, 0xde, 0xd7, 0xd0,
0x13, 0x44, 0x2e, 0xf0, 0xd1, 0x90, 0x65, 0x77, 0xef, 0xbd, 0xe9, 0xd3, 0x09, 0x9a, 0xbf, 0xfb,
0xbd, 0x1a, 0xa3, 0x3f, 0xab, 0x31, 0xfa, 0xbb, 0x1a, 0xa3, 0x8b, 0xd7, 0x45, 0xe9, 0x65, 0x23,
0x68, 0xae, 0x2b, 0x66, 0xec, 0x95, 0xab, 0xb8, 0x2f, 0x73, 0xc5, 0x85, 0xeb, 0x22, 0xb6, 0x7d,
0xf3, 0x6f, 0xc0, 0x4b, 0xf1, 0x20, 0xe4, 0x5f, 0xfd, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x8a, 0x43,
0x60, 0x04, 0x91, 0x03, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -62,7 +177,7 @@ const _ = grpc.SupportPackageIsVersion4
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type SlasherClient interface {
IsSlashableAttestation(ctx context.Context, in *Attestation, opts ...grpc.CallOption) (*AttesterSlashing, error)
IsSlashableBlock(ctx context.Context, in *BeaconBlockHeader, opts ...grpc.CallOption) (*ProposerSlashing, error)
IsSlashableBlock(ctx context.Context, in *ProposerSlashingRequest, opts ...grpc.CallOption) (*ProposerSlashingResponse, error)
SlashableProposals(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (Slasher_SlashableProposalsClient, error)
SlashableAttestations(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (Slasher_SlashableAttestationsClient, error)
}
@@ -84,8 +199,8 @@ func (c *slasherClient) IsSlashableAttestation(ctx context.Context, in *Attestat
return out, nil
}
func (c *slasherClient) IsSlashableBlock(ctx context.Context, in *BeaconBlockHeader, opts ...grpc.CallOption) (*ProposerSlashing, error) {
out := new(ProposerSlashing)
func (c *slasherClient) IsSlashableBlock(ctx context.Context, in *ProposerSlashingRequest, opts ...grpc.CallOption) (*ProposerSlashingResponse, error) {
out := new(ProposerSlashingResponse)
err := c.cc.Invoke(ctx, "/ethereum.eth.v1alpha1.Slasher/IsSlashableBlock", in, out, opts...)
if err != nil {
return nil, err
@@ -160,7 +275,7 @@ func (x *slasherSlashableAttestationsClient) Recv() (*AttesterSlashing, error) {
// SlasherServer is the server API for Slasher service.
type SlasherServer interface {
IsSlashableAttestation(context.Context, *Attestation) (*AttesterSlashing, error)
IsSlashableBlock(context.Context, *BeaconBlockHeader) (*ProposerSlashing, error)
IsSlashableBlock(context.Context, *ProposerSlashingRequest) (*ProposerSlashingResponse, error)
SlashableProposals(*types.Empty, Slasher_SlashableProposalsServer) error
SlashableAttestations(*types.Empty, Slasher_SlashableAttestationsServer) error
}
@@ -188,7 +303,7 @@ func _Slasher_IsSlashableAttestation_Handler(srv interface{}, ctx context.Contex
}
func _Slasher_IsSlashableBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BeaconBlockHeader)
in := new(ProposerSlashingRequest)
if err := dec(in); err != nil {
return nil, err
}
@@ -200,7 +315,7 @@ func _Slasher_IsSlashableBlock_Handler(srv interface{}, ctx context.Context, dec
FullMethod: "/ethereum.eth.v1alpha1.Slasher/IsSlashableBlock",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(SlasherServer).IsSlashableBlock(ctx, req.(*BeaconBlockHeader))
return srv.(SlasherServer).IsSlashableBlock(ctx, req.(*ProposerSlashingRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -274,3 +389,439 @@ var _Slasher_serviceDesc = grpc.ServiceDesc{
},
Metadata: "proto/eth/v1alpha1/slasher.proto",
}
func (m *ProposerSlashingRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ProposerSlashingRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.BlockHeader != nil {
dAtA[i] = 0xa
i++
i = encodeVarintSlasher(dAtA, i, uint64(m.BlockHeader.Size()))
n1, err := m.BlockHeader.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
}
if m.ValidatorIndex != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintSlasher(dAtA, i, uint64(m.ValidatorIndex))
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func (m *ProposerSlashingResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ProposerSlashingResponse) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if len(m.ProposerSlashing) > 0 {
for _, msg := range m.ProposerSlashing {
dAtA[i] = 0xa
i++
i = encodeVarintSlasher(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
return i, nil
}
func encodeVarintSlasher(dAtA []byte, offset int, v uint64) int {
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
}
func (m *ProposerSlashingRequest) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.BlockHeader != nil {
l = m.BlockHeader.Size()
n += 1 + l + sovSlasher(uint64(l))
}
if m.ValidatorIndex != 0 {
n += 1 + sovSlasher(uint64(m.ValidatorIndex))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func (m *ProposerSlashingResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.ProposerSlashing) > 0 {
for _, e := range m.ProposerSlashing {
l = e.Size()
n += 1 + l + sovSlasher(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovSlasher(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
}
func sozSlasher(x uint64) (n int) {
return sovSlasher(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *ProposerSlashingRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSlasher
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ProposerSlashingRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ProposerSlashingRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field BlockHeader", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSlasher
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSlasher
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSlasher
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.BlockHeader == nil {
m.BlockHeader = &BeaconBlockHeader{}
}
if err := m.BlockHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field ValidatorIndex", wireType)
}
m.ValidatorIndex = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSlasher
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.ValidatorIndex |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
default:
iNdEx = preIndex
skippy, err := skipSlasher(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthSlasher
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthSlasher
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ProposerSlashingResponse) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSlasher
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ProposerSlashingResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ProposerSlashingResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ProposerSlashing", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowSlasher
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthSlasher
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthSlasher
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.ProposerSlashing = append(m.ProposerSlashing, &ProposerSlashing{})
if err := m.ProposerSlashing[len(m.ProposerSlashing)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipSlasher(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthSlasher
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthSlasher
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipSlasher(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSlasher
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSlasher
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSlasher
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthSlasher
}
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthSlasher
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowSlasher
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipSlasher(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthSlasher
}
}
return iNdEx, nil
case 4:
return iNdEx, nil
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
}
panic("unreachable")
}
var (
ErrInvalidLengthSlasher = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowSlasher = fmt.Errorf("proto: integer overflow")
)

View File

@@ -21,7 +21,7 @@ service Slasher {
// Gets ProposerSlashing container if the block header that
// was received produces a slashable event.
rpc IsSlashableBlock(ethereum.eth.v1alpha1.BeaconBlockHeader) returns (ethereum.eth.v1alpha1.ProposerSlashing);
rpc IsSlashableBlock(ProposerSlashingRequest) returns (ProposerSlashingResponse);
// Subscription to receive all slashable proposer slashing events found by the watchtower.
rpc SlashableProposals(google.protobuf.Empty) returns (stream ethereum.eth.v1alpha1.ProposerSlashing);
@@ -29,3 +29,10 @@ service Slasher {
// Subscription to receive all slashable attester slashing events found by the watchtower.
rpc SlashableAttestations(google.protobuf.Empty) returns (stream ethereum.eth.v1alpha1.AttesterSlashing);
}
message ProposerSlashingRequest {
ethereum.eth.v1alpha1.BeaconBlockHeader block_header=1;
uint64 validator_index=2;
}
message ProposerSlashingResponse {
repeated ethereum.eth.v1alpha1.ProposerSlashing proposer_slashing=1;
}

30
slasher/BUILD.bazel Normal file
View File

@@ -0,0 +1,30 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "github.com/prysmaticlabs/prysm/slasher",
visibility = ["//slasher:__subpackages__"],
deps = [
"//slasher/db:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_middleware//recovery:go_default_library",
"@com_github_grpc_ecosystem_go_grpc_prometheus//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opencensus_go//plugin/ocgrpc:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
"@org_golang_google_grpc//reflection:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
deps = [
"//shared/testutil:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
],
)

View File

@@ -6,6 +6,7 @@ go_library(
"block_header.go",
"db.go",
"schema.go",
"setup_db.go",
],
importpath = "github.com/prysmaticlabs/prysm/slasher/db",
visibility = ["//slasher:__subpackages__"],
@@ -24,11 +25,8 @@ go_test(
name = "go_default_test",
srcs = [
"block_header_test.go",
"db_test.go",
"setup_db_test.go",
],
embed = [":go_default_library"],
deps = [
"//proto/eth/v1alpha1:go_default_library",
"//shared/testutil:go_default_library",
],
deps = ["//proto/eth/v1alpha1:go_default_library"],
)

View File

@@ -23,7 +23,7 @@ func createBlockHeader(enc []byte) (*ethpb.BeaconBlockHeader, error) {
// BlockHeader accepts an epoch and validator id and returns the corresponding block header array.
// Returns nil if the block header for those values does not exist.
func (db *Store) BlockHeader(epoch uint64, validatorID uint64) ([]*ethpb.BeaconBlockHeader, error) {
var bha []*ethpb.BeaconBlockHeader
var blockHeaders []*ethpb.BeaconBlockHeader
err := db.view(func(tx *bolt.Tx) error {
c := tx.Bucket(historicBlockHeadersBucket).Cursor()
prefix := encodeEpochValidatorID(epoch, validatorID)
@@ -32,11 +32,11 @@ func (db *Store) BlockHeader(epoch uint64, validatorID uint64) ([]*ethpb.BeaconB
if err != nil {
return err
}
bha = append(bha, bh)
blockHeaders = append(blockHeaders, bh)
}
return nil
})
return bha, err
return blockHeaders, err
}
// HasBlockHeader accepts an epoch and validator id and returns true if the block header exists.
@@ -76,7 +76,7 @@ func (db *Store) SaveBlockHeader(epoch uint64, validatorID uint64, blockHeader *
// prune history to max size every 10th epoch
if epoch%params.BeaconConfig().PruneSlasherStoragePeriod == 0 {
err = db.pruneHistory(epoch, params.BeaconConfig().WeakSubjectivityPeriod)
err = db.PruneHistory(epoch, params.BeaconConfig().WeakSubjectivityPeriod)
}
return err
}
@@ -95,7 +95,8 @@ func (db *Store) DeleteBlockHeader(epoch uint64, validatorID uint64, blockHeader
})
}
func (db *Store) pruneHistory(currentEpoch uint64, historySize uint64) error {
// PruneHistory leaves only records younger then history size.
func (db *Store) PruneHistory(currentEpoch uint64, historySize uint64) error {
pruneTill := int64(currentEpoch) - int64(historySize)
if pruneTill <= 0 {
return nil

View File

@@ -8,8 +8,8 @@ import (
)
func TestNilDBHistoryBlkHdr(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
db := SetupSlasherDB(t)
defer TeardownSlasherDB(t, db)
epoch := uint64(1)
validatorID := uint64(1)
@@ -29,8 +29,8 @@ func TestNilDBHistoryBlkHdr(t *testing.T) {
}
func TestSaveHistoryBlkHdr(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
db := SetupSlasherDB(t)
defer TeardownSlasherDB(t, db)
tests := []struct {
epoch uint64
vID uint64
@@ -72,8 +72,8 @@ func TestSaveHistoryBlkHdr(t *testing.T) {
}
func TestDeleteHistoryBlkHdr(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
db := SetupSlasherDB(t)
defer TeardownSlasherDB(t, db)
tests := []struct {
epoch uint64
vID uint64
@@ -130,8 +130,8 @@ func TestDeleteHistoryBlkHdr(t *testing.T) {
}
func TestHasHistoryBlkHdr(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
db := SetupSlasherDB(t)
defer TeardownSlasherDB(t, db)
tests := []struct {
epoch uint64
vID uint64
@@ -179,8 +179,8 @@ func TestHasHistoryBlkHdr(t *testing.T) {
}
func TestPruneHistoryBlkHdr(t *testing.T) {
db := setupDB(t)
defer teardownDB(t, db)
db := SetupSlasherDB(t)
defer TeardownSlasherDB(t, db)
tests := []struct {
epoch uint64
vID uint64
@@ -230,7 +230,7 @@ func TestPruneHistoryBlkHdr(t *testing.T) {
}
currentEpoch := uint64(3)
historyToKeep := uint64(2)
err := db.pruneHistory(currentEpoch, historyToKeep)
err := db.PruneHistory(currentEpoch, historyToKeep)
if err != nil {
t.Fatalf("failed to prune: %v", err)
}

View File

@@ -1,7 +1,6 @@
package db
import (
"io"
"os"
"path"
"time"
@@ -11,16 +10,7 @@ import (
"github.com/sirupsen/logrus"
)
var log = logrus.WithField("prefix", "beacondb")
// Database defines the necessary methods for slasher service which may
// be implemented by any key-value or relational database in practice.
type Database interface {
io.Closer
DatabasePath() string
ClearDB() error
}
var log = logrus.WithField("prefix", "slasherDB")
// Store defines an implementation of the Prysm Database interface
// using BoltDB as the underlying persistent kv-store for eth2.

View File

@@ -1,54 +0,0 @@
package db
import (
"crypto/rand"
"fmt"
"math/big"
"os"
"path"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
var _ = Database(&Store{})
// setupDB instantiates and returns a SlasherDB instance.
func setupDB(t testing.TB) *Store {
randPath, err := rand.Int(rand.Reader, big.NewInt(1000000))
if err != nil {
t.Fatalf("Could not generate random file path: %v", err)
}
path := path.Join(testutil.TempDir(), fmt.Sprintf("/%d", randPath))
if err := os.RemoveAll(path); err != nil {
t.Fatalf("Failed to remove directory: %v", err)
}
db, err := NewDB(path)
if err != nil {
t.Fatalf("Failed to instantiate DB: %v", err)
}
return db
}
// teardownDB cleans up a test BeaconDB instance.
func teardownDB(t testing.TB, db *Store) {
if err := db.Close(); err != nil {
t.Fatalf("Failed to close database: %v", err)
}
if err := os.RemoveAll(db.DatabasePath()); err != nil {
t.Fatalf("Failed to remove directory: %v", err)
}
}
func TestClearDB(t *testing.T) {
slasherDB := setupDB(t)
if err := slasherDB.ClearDB(); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(slasherDB.DatabasePath()); !os.IsNotExist(err) {
t.Fatalf("db wasnt cleared %v", err)
}
}

49
slasher/db/setup_db.go Normal file
View File

@@ -0,0 +1,49 @@
package db
import (
"crypto/rand"
"fmt"
"math/big"
"os"
"path"
"testing"
)
// SetupSlasherDB instantiates and returns a SlasherDB instance.
func SetupSlasherDB(t testing.TB) *Store {
randPath, err := rand.Int(rand.Reader, big.NewInt(1000000))
if err != nil {
t.Fatalf("Could not generate random file path: %v", err)
}
p := path.Join(TempDir(), fmt.Sprintf("/%d", randPath))
if err := os.RemoveAll(p); err != nil {
t.Fatalf("Failed to remove directory: %v", err)
}
db, err := NewDB(p)
if err != nil {
t.Fatalf("Failed to instantiate DB: %v", err)
}
return db
}
// TempDir returns a directory path for temporary test storage.
func TempDir() string {
d := os.Getenv("TEST_TMPDIR")
// If the test is not run via bazel, the environment var won't be set.
if d == "" {
return os.TempDir()
}
return d
}
// TeardownSlasherDB cleans up a test BeaconDB instance.
func TeardownSlasherDB(t testing.TB, db *Store) {
if err := db.Close(); err != nil {
t.Fatalf("Failed to close database: %v", err)
}
if err := os.RemoveAll(db.DatabasePath()); err != nil {
t.Fatalf("Failed to remove directory: %v", err)
}
}

View File

@@ -0,0 +1,18 @@
package db
import (
"os"
"testing"
)
func TestClearDB(t *testing.T) {
slasherDB := SetupSlasherDB(t)
defer TeardownSlasherDB(t, slasherDB)
if err := slasherDB.ClearDB(); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(slasherDB.DatabasePath()); !os.IsNotExist(err) {
t.Fatalf("db wasnt cleared %v", err)
}
}

120
slasher/service.go Normal file
View File

@@ -0,0 +1,120 @@
// Package slasher defines the service used to retrieve slashings proofs.
package slasher
import (
"fmt"
"net"
middleware "github.com/grpc-ecosystem/go-grpc-middleware"
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/prysmaticlabs/prysm/slasher/db"
"github.com/sirupsen/logrus"
"go.opencensus.io/plugin/ocgrpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/reflection"
)
var log logrus.FieldLogger
func init() {
log = logrus.WithField("prefix", "slasherRPC")
}
// Service defining an RPC server for the slasher service.
type Service struct {
slasherDb *db.Store
grpcServer *grpc.Server
port string
withCert string
withKey string
listener net.Listener
credentialError error
failStatus error
}
// Config options for the slasher server.
type Config struct {
Port string
CertFlag string
KeyFlag string
SlasherDb *db.Store
}
// NewRPCService creates a new instance of a struct implementing the SlasherService
// interface.
func NewRPCService(cfg *Config) *Service {
return &Service{
slasherDb: cfg.SlasherDb,
port: cfg.Port,
}
}
// Start the gRPC server.
func (s *Service) Start() {
log.Info("Starting service on port: %v", s.port)
lis, err := net.Listen("tcp", fmt.Sprintf(":%s", s.port))
if err != nil {
log.Errorf("Could not listen to port in Start() :%s: %v", s.port, err)
}
s.listener = lis
log.WithField("port", s.port).Info("Listening on port")
opts := []grpc.ServerOption{
grpc.StatsHandler(&ocgrpc.ServerHandler{}),
grpc.StreamInterceptor(middleware.ChainStreamServer(
recovery.StreamServerInterceptor(),
grpc_prometheus.StreamServerInterceptor,
)),
grpc.UnaryInterceptor(middleware.ChainUnaryServer(
recovery.UnaryServerInterceptor(),
grpc_prometheus.UnaryServerInterceptor,
)),
}
// TODO(#791): Utilize a certificate for secure connections
// between beacon nodes and validator clients.
if s.withCert != "" && s.withKey != "" {
creds, err := credentials.NewServerTLSFromFile(s.withCert, s.withKey)
if err != nil {
log.Errorf("Could not load TLS keys: %s", err)
s.credentialError = err
}
opts = append(opts, grpc.Creds(creds))
} else {
log.Warn("You are using an insecure gRPC connection! Provide a certificate and key to connect securely")
}
s.grpcServer = grpc.NewServer(opts...)
// Register reflection service on gRPC server.
reflection.Register(s.grpcServer)
go func() {
if s.listener != nil {
if err := s.grpcServer.Serve(s.listener); err != nil {
log.Errorf("Could not serve gRPC: %v", err)
}
}
}()
}
// Stop the service.
func (s *Service) Stop() error {
log.Info("Stopping service")
if s.listener != nil {
s.grpcServer.GracefulStop()
log.Debug("Initiated graceful stop of gRPC server")
}
return nil
}
// Status returns nil, credentialError or fail status.
func (s *Service) Status() error {
if s.credentialError != nil {
return s.credentialError
}
if s.failStatus != nil {
return s.failStatus
}
return nil
}

79
slasher/service_test.go Normal file
View File

@@ -0,0 +1,79 @@
package slasher
import (
"errors"
"fmt"
"io/ioutil"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus"
logTest "github.com/sirupsen/logrus/hooks/test"
)
func init() {
logrus.SetLevel(logrus.DebugLevel)
logrus.SetOutput(ioutil.Discard)
}
func TestLifecycle_OK(t *testing.T) {
hook := logTest.NewGlobal()
rpcService := NewRPCService(&Config{
Port: "7348",
CertFlag: "alice.crt",
KeyFlag: "alice.key",
})
rpcService.Start()
testutil.AssertLogsContain(t, hook, "Starting service")
testutil.AssertLogsContain(t, hook, "Listening on port")
rpcService.Stop()
testutil.AssertLogsContain(t, hook, "Stopping service")
}
func TestRPC_BadEndpoint(t *testing.T) {
hook := logTest.NewGlobal()
rpcService := NewRPCService(&Config{
Port: "ralph merkle!!!",
})
testutil.AssertLogsDoNotContain(t, hook, "Could not listen to port in Start()")
testutil.AssertLogsDoNotContain(t, hook, "Could not load TLS keys")
testutil.AssertLogsDoNotContain(t, hook, "Could not serve gRPC")
rpcService.Start()
testutil.AssertLogsContain(t, hook, "Starting service")
testutil.AssertLogsContain(t, hook, "Could not listen to port in Start()")
rpcService.Stop()
}
func TestStatus_CredentialError(t *testing.T) {
credentialErr := errors.New("credentialError")
s := &Service{credentialError: credentialErr}
if err := s.Status(); err != s.credentialError {
t.Errorf("Wanted: %v, got: %v", s.credentialError, s.Status())
}
}
func TestRPC_InsecureEndpoint(t *testing.T) {
hook := logTest.NewGlobal()
rpcService := NewRPCService(&Config{
Port: "7777",
})
rpcService.Start()
testutil.AssertLogsContain(t, hook, "Starting service")
testutil.AssertLogsContain(t, hook, fmt.Sprint("Listening on port"))
testutil.AssertLogsContain(t, hook, "You are using an insecure gRPC connection")
rpcService.Stop()
testutil.AssertLogsContain(t, hook, "Stopping service")
}