Refactor x/evidence to ADR-031 (#7538)

* Refactor x/evidence to ADR-031

* Add hash in response

* Update changelog

* Update x/evidence/keeper/keeper.go

* Update proto/cosmos/evidence/v1beta1/tx.proto

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>

* Use msgServer struct

Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
This commit is contained in:
Amaury Martiny 2020-10-16 18:05:25 +02:00 committed by GitHub
parent 18ef33caff
commit 58eabcb71f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 376 additions and 40 deletions

View File

@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Client Breaking
* (x/staking) [\#7499](https://github.com/cosmos/cosmos-sdk/pull/7499) `BondStatus` is now a protobuf `enum` instead of an `int32`, and JSON serialized using its protobuf name, so expect names like `BOND_STATUS_UNBONDING` as opposed to `Unbonding`.
* (x/evidence) [\#7538](https://github.com/cosmos/cosmos-sdk/pull/7538) The ABCI's `Result.Data` field of `MsgSubmitEvidence` does not contain the raw evidence's hash, but the encoded `MsgSubmitEvidenceResponse` struct.
### API Breaking

View File

@ -8,6 +8,13 @@ import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cosmos_proto/cosmos.proto";
// Msg defines the evidence Msg service.
service Msg {
// SubmitEvidence submits an arbitrary Evidence of misbehavior such as equivocation or
// counterfactual signing.
rpc SubmitEvidence(MsgSubmitEvidence) returns (MsgSubmitEvidenceResponse);
}
// MsgSubmitEvidence represents a message that supports submitting arbitrary
// Evidence of misbehavior such as equivocation or counterfactual signing.
message MsgSubmitEvidence {
@ -17,3 +24,9 @@ message MsgSubmitEvidence {
string submitter = 1;
google.protobuf.Any evidence = 2 [(cosmos_proto.accepts_interface) = "Evidence"];
}
// MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type.
message MsgSubmitEvidenceResponse {
// hash defines the hash of the evidence.
bytes hash = 4;
}

View File

@ -9,11 +9,11 @@ import (
// NewHandler returns a handler for "bank" type messages.
func NewHandler(k keeper.Keeper) sdk.Handler {
msgServer := keeper.NewMsgServerImpl(k)
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
msgServer := keeper.NewMsgServerImpl(k)
switch msg := msg.(type) {
case *types.MsgSend:
res, err := msgServer.Send(sdk.WrapSDKContext(ctx), msg)

View File

@ -34,10 +34,10 @@ type ValidatorEvidence interface {
GetTotalPower() int64
}
// MsgSubmitEvidence defines the specific interface a concrete message must
// MsgSubmitEvidenceI defines the specific interface a concrete message must
// implement in order to process submitted evidence. The concrete MsgSubmitEvidence
// must be defined at the application-level.
type MsgSubmitEvidence interface {
type MsgSubmitEvidenceI interface {
sdk.Msg
GetEvidence() Evidence

View File

@ -3,42 +3,24 @@ package evidence
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/evidence/exported"
"github.com/cosmos/cosmos-sdk/x/evidence/keeper"
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)
// NewHandler returns a handler for evidence messages.
func NewHandler(k keeper.Keeper) sdk.Handler {
msgServer := keeper.NewMsgServerImpl(k)
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
ctx = ctx.WithEventManager(sdk.NewEventManager())
switch msg := msg.(type) {
case exported.MsgSubmitEvidence:
return handleMsgSubmitEvidence(ctx, k, msg)
case *types.MsgSubmitEvidence:
res, err := msgServer.SubmitEvidence(sdk.WrapSDKContext(ctx), msg)
return sdk.WrapServiceResult(ctx, res, err)
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", types.ModuleName, msg)
}
}
}
func handleMsgSubmitEvidence(ctx sdk.Context, k keeper.Keeper, msg exported.MsgSubmitEvidence) (*sdk.Result, error) {
evidence := msg.GetEvidence()
if err := k.SubmitEvidence(ctx, evidence); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.GetSubmitter().String()),
),
)
return &sdk.Result{
Data: evidence.Hash(),
Events: ctx.EventManager().ABCIEvents(),
}, nil
}

View File

@ -25,7 +25,7 @@ type HandlerTestSuite struct {
app *simapp.SimApp
}
func testMsgSubmitEvidence(r *require.Assertions, e exported.Evidence, s sdk.AccAddress) exported.MsgSubmitEvidence {
func testMsgSubmitEvidence(r *require.Assertions, e exported.Evidence, s sdk.AccAddress) exported.MsgSubmitEvidenceI {
msg, err := types.NewMsgSubmitEvidence(s, e)
r.NoError(err)
return msg
@ -113,8 +113,11 @@ func (suite *HandlerTestSuite) TestMsgSubmitEvidence() {
suite.Require().NoError(err, "unexpected error; tc #%d", i)
suite.Require().NotNil(res, "expected non-nil result; tc #%d", i)
msg := tc.msg.(exported.MsgSubmitEvidence)
suite.Require().Equal(msg.GetEvidence().Hash().Bytes(), res.Data, "invalid hash; tc #%d", i)
msg := tc.msg.(exported.MsgSubmitEvidenceI)
var resultData types.MsgSubmitEvidenceResponse
suite.app.AppCodec().UnmarshalBinaryBare(res.Data, &resultData)
suite.Require().Equal(msg.GetEvidence().Hash().Bytes(), resultData.Hash, "invalid hash; tc #%d", i)
}
}
}

View File

@ -0,0 +1,42 @@
package keeper
import (
"context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)
type msgServer struct {
Keeper
}
// NewMsgServerImpl returns an implementation of the bank MsgServer interface
// for the provided Keeper.
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
return &msgServer{Keeper: keeper}
}
var _ types.MsgServer = msgServer{}
// SubmitEvidence implements the MsgServer.SubmitEvidence method.
func (ms msgServer) SubmitEvidence(goCtx context.Context, msg *types.MsgSubmitEvidence) (*types.MsgSubmitEvidenceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
evidence := msg.GetEvidence()
if err := ms.Keeper.SubmitEvidence(ctx, evidence); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.GetSubmitter().String()),
),
)
return &types.MsgSubmitEvidenceResponse{
Hash: evidence.Hash(),
}, nil
}

View File

@ -19,7 +19,7 @@ const (
var (
_ sdk.Msg = &MsgSubmitEvidence{}
_ types.UnpackInterfacesMessage = MsgSubmitEvidence{}
_ exported.MsgSubmitEvidence = &MsgSubmitEvidence{}
_ exported.MsgSubmitEvidenceI = &MsgSubmitEvidence{}
)
// NewMsgSubmitEvidence returns a new MsgSubmitEvidence with a signer/submitter.

View File

@ -12,7 +12,7 @@ import (
"github.com/cosmos/cosmos-sdk/x/evidence/types"
)
func testMsgSubmitEvidence(t *testing.T, e exported.Evidence, s sdk.AccAddress) exported.MsgSubmitEvidence {
func testMsgSubmitEvidence(t *testing.T, e exported.Evidence, s sdk.AccAddress) exported.MsgSubmitEvidenceI {
msg, err := types.NewMsgSubmitEvidence(s, e)
require.NoError(t, err)
return msg

View File

@ -4,11 +4,17 @@
package types
import (
bytes "bytes"
context "context"
fmt "fmt"
types "github.com/cosmos/cosmos-sdk/codec/types"
_ "github.com/gogo/protobuf/gogoproto"
grpc1 "github.com/gogo/protobuf/grpc"
proto "github.com/gogo/protobuf/proto"
_ "github.com/regen-network/cosmos-proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
io "io"
math "math"
math_bits "math/bits"
@ -65,14 +71,61 @@ func (m *MsgSubmitEvidence) XXX_DiscardUnknown() {
var xxx_messageInfo_MsgSubmitEvidence proto.InternalMessageInfo
// MsgSubmitEvidenceResponse defines the Msg/SubmitEvidence response type.
type MsgSubmitEvidenceResponse struct {
// hash defines the hash of the evidence.
Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"`
}
func (m *MsgSubmitEvidenceResponse) Reset() { *m = MsgSubmitEvidenceResponse{} }
func (m *MsgSubmitEvidenceResponse) String() string { return proto.CompactTextString(m) }
func (*MsgSubmitEvidenceResponse) ProtoMessage() {}
func (*MsgSubmitEvidenceResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_3e3242cb23c956e0, []int{1}
}
func (m *MsgSubmitEvidenceResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *MsgSubmitEvidenceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_MsgSubmitEvidenceResponse.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *MsgSubmitEvidenceResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgSubmitEvidenceResponse.Merge(m, src)
}
func (m *MsgSubmitEvidenceResponse) XXX_Size() int {
return m.Size()
}
func (m *MsgSubmitEvidenceResponse) XXX_DiscardUnknown() {
xxx_messageInfo_MsgSubmitEvidenceResponse.DiscardUnknown(m)
}
var xxx_messageInfo_MsgSubmitEvidenceResponse proto.InternalMessageInfo
func (m *MsgSubmitEvidenceResponse) GetHash() []byte {
if m != nil {
return m.Hash
}
return nil
}
func init() {
proto.RegisterType((*MsgSubmitEvidence)(nil), "cosmos.evidence.v1beta1.MsgSubmitEvidence")
proto.RegisterType((*MsgSubmitEvidenceResponse)(nil), "cosmos.evidence.v1beta1.MsgSubmitEvidenceResponse")
}
func init() { proto.RegisterFile("cosmos/evidence/v1beta1/tx.proto", fileDescriptor_3e3242cb23c956e0) }
var fileDescriptor_3e3242cb23c956e0 = []byte{
// 257 bytes of a gzipped FileDescriptorProto
// 316 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x48, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0x4f, 0x2d, 0xcb, 0x4c, 0x49, 0xcd, 0x4b, 0x4e, 0xd5, 0x2f, 0x33, 0x4c, 0x4a,
0x2d, 0x49, 0x34, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x87, 0xa8,
@ -84,12 +137,124 @@ var fileDescriptor_3e3242cb23c956e0 = []byte{
0x10, 0x42, 0x40, 0xc8, 0x8e, 0x8b, 0x03, 0xe6, 0x24, 0x09, 0x26, 0x05, 0x46, 0x0d, 0x6e, 0x23,
0x11, 0x3d, 0x88, 0xdd, 0x7a, 0x30, 0xbb, 0xf5, 0x1c, 0xf3, 0x2a, 0x9d, 0x78, 0x4e, 0x6d, 0xd1,
0xe5, 0x80, 0x99, 0x19, 0x04, 0xd7, 0x63, 0xc5, 0xd1, 0xb1, 0x40, 0x9e, 0xe1, 0xc5, 0x02, 0x79,
0x06, 0x27, 0xef, 0x15, 0x8f, 0xe4, 0x18, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1,
0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e,
0x21, 0x4a, 0x37, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x17, 0xea, 0x66, 0x28,
0xa5, 0x5b, 0x9c, 0x92, 0xad, 0x5f, 0x81, 0x08, 0xb9, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36,
0xb0, 0xe5, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x60, 0x3b, 0xe2, 0x83, 0x59, 0x01, 0x00,
0x00,
0x06, 0x25, 0x7d, 0x2e, 0x49, 0x0c, 0xcb, 0x83, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85,
0x84, 0xb8, 0x58, 0x32, 0x12, 0x8b, 0x33, 0x24, 0x58, 0x14, 0x18, 0x35, 0x78, 0x82, 0xc0, 0x6c,
0xa3, 0x72, 0x2e, 0x66, 0xdf, 0xe2, 0x74, 0xa1, 0x02, 0x2e, 0x3e, 0x34, 0x17, 0x6b, 0xe9, 0xe1,
0x08, 0x2c, 0x3d, 0x0c, 0x0b, 0xa4, 0x8c, 0x88, 0x57, 0x0b, 0x73, 0x8c, 0x93, 0xf7, 0x8a, 0x47,
0x72, 0x8c, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84,
0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x9b, 0x9e, 0x59,
0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0x0b, 0x0d, 0x5d, 0x28, 0xa5, 0x5b, 0x9c, 0x92, 0xad,
0x5f, 0x81, 0x88, 0xe3, 0x92, 0xca, 0x82, 0xd4, 0xe2, 0x24, 0x36, 0x70, 0x30, 0x19, 0x03, 0x02,
0x00, 0x00, 0xff, 0xff, 0xa7, 0x78, 0xdf, 0xa8, 0x03, 0x02, 0x00, 0x00,
}
func (this *MsgSubmitEvidenceResponse) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*MsgSubmitEvidenceResponse)
if !ok {
that2, ok := that.(MsgSubmitEvidenceResponse)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if !bytes.Equal(this.Hash, that1.Hash) {
return false
}
return true
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// MsgClient is the client API for Msg service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type MsgClient interface {
// Send submits an arbitrary Evidence of misbehavior such as equivocation or
// counterfactual signing.
SubmitEvidence(ctx context.Context, in *MsgSubmitEvidence, opts ...grpc.CallOption) (*MsgSubmitEvidenceResponse, error)
}
type msgClient struct {
cc grpc1.ClientConn
}
func NewMsgClient(cc grpc1.ClientConn) MsgClient {
return &msgClient{cc}
}
func (c *msgClient) SubmitEvidence(ctx context.Context, in *MsgSubmitEvidence, opts ...grpc.CallOption) (*MsgSubmitEvidenceResponse, error) {
out := new(MsgSubmitEvidenceResponse)
err := c.cc.Invoke(ctx, "/cosmos.evidence.v1beta1.Msg/SubmitEvidence", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// MsgServer is the server API for Msg service.
type MsgServer interface {
// Send submits an arbitrary Evidence of misbehavior such as equivocation or
// counterfactual signing.
SubmitEvidence(context.Context, *MsgSubmitEvidence) (*MsgSubmitEvidenceResponse, error)
}
// UnimplementedMsgServer can be embedded to have forward compatible implementations.
type UnimplementedMsgServer struct {
}
func (*UnimplementedMsgServer) SubmitEvidence(ctx context.Context, req *MsgSubmitEvidence) (*MsgSubmitEvidenceResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SubmitEvidence not implemented")
}
func RegisterMsgServer(s grpc1.Server, srv MsgServer) {
s.RegisterService(&_Msg_serviceDesc, srv)
}
func _Msg_SubmitEvidence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(MsgSubmitEvidence)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MsgServer).SubmitEvidence(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cosmos.evidence.v1beta1.Msg/SubmitEvidence",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MsgServer).SubmitEvidence(ctx, req.(*MsgSubmitEvidence))
}
return interceptor(ctx, in, info, handler)
}
var _Msg_serviceDesc = grpc.ServiceDesc{
ServiceName: "cosmos.evidence.v1beta1.Msg",
HandlerType: (*MsgServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SubmitEvidence",
Handler: _Msg_SubmitEvidence_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "cosmos/evidence/v1beta1/tx.proto",
}
func (m *MsgSubmitEvidence) Marshal() (dAtA []byte, err error) {
@ -134,6 +299,36 @@ func (m *MsgSubmitEvidence) MarshalToSizedBuffer(dAtA []byte) (int, error) {
return len(dAtA) - i, nil
}
func (m *MsgSubmitEvidenceResponse) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *MsgSubmitEvidenceResponse) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *MsgSubmitEvidenceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Hash) > 0 {
i -= len(m.Hash)
copy(dAtA[i:], m.Hash)
i = encodeVarintTx(dAtA, i, uint64(len(m.Hash)))
i--
dAtA[i] = 0x22
}
return len(dAtA) - i, nil
}
func encodeVarintTx(dAtA []byte, offset int, v uint64) int {
offset -= sovTx(v)
base := offset
@ -162,6 +357,19 @@ func (m *MsgSubmitEvidence) Size() (n int) {
return n
}
func (m *MsgSubmitEvidenceResponse) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Hash)
if l > 0 {
n += 1 + l + sovTx(uint64(l))
}
return n
}
func sovTx(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
@ -289,6 +497,93 @@ func (m *MsgSubmitEvidence) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *MsgSubmitEvidenceResponse) 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 ErrIntOverflowTx
}
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: MsgSubmitEvidenceResponse: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: MsgSubmitEvidenceResponse: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Hash", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowTx
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthTx
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthTx
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Hash = append(m.Hash[:0], dAtA[iNdEx:postIndex]...)
if m.Hash == nil {
m.Hash = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipTx(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthTx
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthTx
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipTx(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0