Skip to content

Commit

Permalink
add a GRPC for program fingerprint
Browse files Browse the repository at this point in the history
  • Loading branch information
skyargos committed Nov 15, 2023
1 parent e2c53fb commit cfc9ddf
Show file tree
Hide file tree
Showing 17 changed files with 1,315 additions and 726 deletions.
52 changes: 31 additions & 21 deletions proto/shentu/bounty/v1/bounty.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@ message Program {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string program_id = 1 [(gogoproto.jsontag) = "id", (gogoproto.moretags) = "yaml:\"id\""];
string program_id = 1 [(gogoproto.moretags) = "yaml:\"program_id\""];
string name = 2 [(gogoproto.moretags) = "yaml:\"name\""];
// JSON by ProgramDetail
string detail = 3 [(gogoproto.moretags) = "yaml:\"detail\""];
string admin_address = 4 [(gogoproto.moretags) = "yaml:\"admin_address\""];
ProgramStatus status = 5 [(gogoproto.moretags) = "yaml:\"status\""];
repeated BountyLevel bounty_levels = 6 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"bounty_levels\""];
google.protobuf.Timestamp create_time = 7
google.protobuf.Timestamp create_time = 6
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"create_time\""];
}

Expand All @@ -29,7 +28,7 @@ message Finding {
option (gogoproto.goproto_getters) = false;

string program_id = 1 [(gogoproto.moretags) = "yaml:\"program_id\""];
string finding_id = 2 [(gogoproto.jsontag) = "id", (gogoproto.moretags) = "yaml:\"id\""];
string finding_id = 2 [(gogoproto.moretags) = "yaml:\"finding_id\""];
string title = 3;
string description = 4 [(gogoproto.moretags) = "yaml:\"description\""];
string proof_of_concept = 5 [(gogoproto.moretags) = "yaml:\"proof_of_concept\""];
Expand All @@ -40,11 +39,24 @@ message Finding {
FindingStatus status = 9 [(gogoproto.moretags) = "yaml:\"status\""];
// JSON by FindingDetail
string detail = 10 [(gogoproto.moretags) = "yaml:\"detail\""];
google.protobuf.Timestamp create_time = 11
string payment_hash = 11 [(gogoproto.moretags) = "yaml:\"payment_hash\""];
google.protobuf.Timestamp create_time = 12
[(gogoproto.stdtime) = true, (gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"create_time\""];
}

message FindingFingerPrint {
message ProgramFingerprint {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

string program_id = 1 [(gogoproto.jsontag) = "id", (gogoproto.moretags) = "yaml:\"id\""];
string name = 2 [(gogoproto.moretags) = "yaml:\"name\""];
// JSON by ProgramDetail
string detail = 3 [(gogoproto.moretags) = "yaml:\"detail\""];
string admin_address = 4 [(gogoproto.moretags) = "yaml:\"admin_address\""];
ProgramStatus status = 5 [(gogoproto.moretags) = "yaml:\"status\""];
}

message FindingFingerprint {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

Expand All @@ -53,10 +65,11 @@ message FindingFingerPrint {
string title = 3;
// hash(description + proof_of_concept + submitter)
string finding_hash = 4 [(gogoproto.moretags) = "yaml:\"finding_hash\""];
SeverityLevel severity_level = 6 [(gogoproto.moretags) = "yaml:\"severity_level\""];
FindingStatus status = 7 [(gogoproto.moretags) = "yaml:\"status\""];
SeverityLevel severity_level = 5 [(gogoproto.moretags) = "yaml:\"severity_level\""];
FindingStatus status = 6 [(gogoproto.moretags) = "yaml:\"status\""];
// JSON by FindingDetail
string detail = 8 [(gogoproto.moretags) = "yaml:\"detail\""];
string detail = 7 [(gogoproto.moretags) = "yaml:\"detail\""];
string payment_hash = 8 [(gogoproto.moretags) = "yaml:\"payment_hash\""];
}

enum ProgramStatus {
Expand Down Expand Up @@ -88,20 +101,19 @@ enum FindingStatus {
FINDING_STATUS_CLOSED = 4 [(gogoproto.enumvalue_customname) = "FindingStatusClosed"];
}

message BountyLevel {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

SeverityLevel severity_level = 1 [(gogoproto.moretags) = "yaml:\"severity_level\""];
bool poc = 2;
cosmos.base.v1beta1.Coin min_bounty = 3 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"min_bounty\""];
cosmos.base.v1beta1.Coin max_bounty = 4 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"max_bounty\""];
}
//message BountyLevel {
// option (gogoproto.equal) = false;
// option (gogoproto.goproto_getters) = false;
//
// SeverityLevel severity_level = 1 [(gogoproto.moretags) = "yaml:\"severity_level\""];
// bool poc = 2;
// cosmos.base.v1beta1.Coin min_bounty = 3 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"min_bounty\""];
// cosmos.base.v1beta1.Coin max_bounty = 4 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"max_bounty\""];
//}

//// ProgramDetail defines a program detail.
//type ProgramDetail struct {
// Type string `json:"type"`
// Name string `json:"name"`
// Logo string `json:"logo"`
// Desc string `json:"desc"`
// Targets []string `json:"targets"`
Expand All @@ -121,6 +133,4 @@ message BountyLevel {
// Attachments []string `json:"attachments"`
// ReceiverInfo ReceiverInfo `json:"receiver_info"`
// PaidInfo PaidInfo `json:"paid_info"`
// FindingHash string `json:"finding_hash"`
// ShentuAddress string `json:"shentu_addr"`
//}
18 changes: 17 additions & 1 deletion proto/shentu/bounty/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ service Query {
option (google.api.http).get = "/shentu/bounty/v1/findings/{finding_id}";
}

// FindingFingerprint queries Finding Fingerprint based on FindingId.
// FindingFingerprint queries finding fingerprint based on findingId.
rpc FindingFingerprint(QueryFindingFingerprintRequest) returns (QueryFindingFingerprintResponse) {
option (google.api.http).get = "/shentu/bounty/v1/findings/{finding_id}/fingerprint";
}

// ProgramFingerprint queries program fingerprint based on programId.
rpc ProgramFingerprint(QueryProgramFingerprintRequest) returns (QueryProgramFingerprintResponse) {
option (google.api.http).get = "/shentu/bounty/v1/programs/{program_id}/fingerprint";
}
}

// QueryHostsRequest is the request type for the Query/Hosts RPC method.
Expand Down Expand Up @@ -118,4 +123,15 @@ message QueryFindingFingerprintRequest {
// QueryFindingFingerPrintResponse is the response type for the Query/Finding RPC method.
message QueryFindingFingerprintResponse {
string fingerprint = 1;
}

// QueryProgramFingerprintRequest is the request type for the Query/Finding RPC method.
message QueryProgramFingerprintRequest {
// program_id defines the unique id of the finding.
string program_id = 1;
}

// QueryProgramFingerprintResponse is the response type for the Query/Finding RPC method.
message QueryProgramFingerprintResponse {
string fingerprint = 1;
}
11 changes: 5 additions & 6 deletions proto/shentu/bounty/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ message MsgCreateProgram {
string program_id = 1 [(gogoproto.moretags) = "yaml:\"program_id\""];
string name = 2;
string detail = 3;
repeated BountyLevel bounty_levels = 4 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"bounty_levels\""];
string operator_address = 5 [(gogoproto.moretags) = "yaml:\"operator_address\""];
string operator_address = 4 [(gogoproto.moretags) = "yaml:\"operator_address\""];
}

// MsgEditProgram defines a SDK message for editing a program.
Expand All @@ -64,8 +63,7 @@ message MsgEditProgram {
string program_id = 1 [(gogoproto.moretags) = "yaml:\"program_id\""];
string name = 2;
string detail = 3;
repeated BountyLevel bounty_levels = 4 [(gogoproto.nullable) = false, (gogoproto.moretags) = "yaml:\"bounty_levels\""];
string operator_address = 5 [(gogoproto.moretags) = "yaml:\"operator_address\""];
string operator_address = 4 [(gogoproto.moretags) = "yaml:\"operator_address\""];
}

// MsgCreateProgramResponse defines the Msg/CreateProgram response type.
Expand Down Expand Up @@ -104,7 +102,7 @@ message MsgSubmitFinding {
string finding_id = 2 [(gogoproto.moretags) = "yaml:\"finding_id\""];
string title = 3;
string finding_hash = 4 [(gogoproto.moretags) = "yaml:\"finding_hash\""];
string submitter_address = 5 [(gogoproto.moretags) = "yaml:\"submitter_address\""];
string operator_address = 5 [(gogoproto.moretags) = "yaml:\"operator_address\""];
SeverityLevel severity_level = 6 [(gogoproto.moretags) = "yaml:\"severity_level\""];
string detail = 7;
}
Expand All @@ -120,9 +118,10 @@ message MsgEditFinding {
string finding_id = 1 [(gogoproto.moretags) = "yaml:\"finding_id\""];
string title = 2;
string finding_hash = 3 [(gogoproto.moretags) = "yaml:\"finding_hash\""];
string submitter_address = 4 [(gogoproto.moretags) = "yaml:\"submitter_address\""];
string operator_address = 4 [(gogoproto.moretags) = "yaml:\"operator_address\""];
SeverityLevel severity_level = 5 [(gogoproto.moretags) = "yaml:\"severity_level\""];
string detail = 6;
string payment_hash = 7 [(gogoproto.moretags) = "yaml:\"payment_hash\""];
}

// MsgEditFindingResponse defines the MsgEditFinding response type.
Expand Down
4 changes: 2 additions & 2 deletions x/bounty/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func NewCreateProgramCmd() *cobra.Command {
return err
}

msg := types.NewMsgCreateProgram(pid, name, desc, creatorAddr, nil)
msg := types.NewMsgCreateProgram(pid, name, desc, creatorAddr)

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
Expand Down Expand Up @@ -102,7 +102,7 @@ func NewEditProgramCmd() *cobra.Command {
return err
}

msg := types.NewMsgEditProgram(pid, name, detail, creatorAddr, nil)
msg := types.NewMsgEditProgram(pid, name, detail, creatorAddr)

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
Expand Down
16 changes: 11 additions & 5 deletions x/bounty/keeper/finding.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ func (k Keeper) ConfirmFinding(ctx sdk.Context, msg *types.MsgConfirmFinding) (t
if !found {
return finding, types.ErrFindingNotExists
}
// only FindingStatusSubmitted
if finding.Status != types.FindingStatusSubmitted {
return finding, types.ErrFindingStatusInvalid
}

Check warning on line 136 in x/bounty/keeper/finding.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/finding.go#L135-L136

Added lines #L135 - L136 were not covered by tests

// get program
program, isExist := k.GetProgram(ctx, finding.ProgramId)
if !isExist {
Expand All @@ -139,31 +144,32 @@ func (k Keeper) ConfirmFinding(ctx sdk.Context, msg *types.MsgConfirmFinding) (t
return finding, types.ErrProgramNotActive
}

Check warning on line 145 in x/bounty/keeper/finding.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/finding.go#L144-L145

Added lines #L144 - L145 were not covered by tests

// only host can update finding comment
// only program admin can confirm finding
if program.AdminAddress != msg.OperatorAddress {
return finding, types.ErrProgramCreatorInvalid
}

Check warning on line 150 in x/bounty/keeper/finding.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/finding.go#L149-L150

Added lines #L149 - L150 were not covered by tests

// fingerprint comparison
fingerprintHash := k.GetFindingFingerPrintHash(&finding)
fingerprintHash := k.GetFindingFingerprintHash(&finding)
if msg.Fingerprint != fingerprintHash {
return finding, types.ErrFindingHashInvalid
}

Check warning on line 156 in x/bounty/keeper/finding.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/finding.go#L155-L156

Added lines #L155 - L156 were not covered by tests
return finding, nil
}

func (k Keeper) GetFindingFingerPrintHash(finding *types.Finding) string {
findingFingerPrint := &types.FindingFingerPrint{
func (k Keeper) GetFindingFingerprintHash(finding *types.Finding) string {
findingFingerprint := &types.FindingFingerprint{
ProgramId: finding.ProgramId,
FindingId: finding.FindingId,
Title: finding.Title,
FindingHash: finding.FindingHash,
SeverityLevel: finding.SeverityLevel,
Status: finding.Status,
Detail: finding.Detail,
PaymentHash: finding.PaymentHash,
}

bz := k.cdc.MustMarshal(findingFingerPrint)
bz := k.cdc.MustMarshal(findingFingerprint)
hash := sha256.Sum256(bz)
return hex.EncodeToString(hash[:])
}
18 changes: 17 additions & 1 deletion x/bounty/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,22 @@ func (k Keeper) FindingFingerprint(c context.Context, req *types.QueryFindingFin
return nil, status.Errorf(codes.NotFound, "finding %s doesn't exist", req.FindingId)
}

Check warning on line 120 in x/bounty/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/grpc_query.go#L116-L120

Added lines #L116 - L120 were not covered by tests

findingFingerPrintHash := k.GetFindingFingerPrintHash(&finding)
findingFingerPrintHash := k.GetFindingFingerprintHash(&finding)
return &types.QueryFindingFingerprintResponse{Fingerprint: findingFingerPrintHash}, nil

Check warning on line 123 in x/bounty/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/grpc_query.go#L122-L123

Added lines #L122 - L123 were not covered by tests
}

func (k Keeper) ProgramFingerprint(c context.Context, req *types.QueryProgramFingerprintRequest) (*types.QueryProgramFingerprintResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "invalid request")
}
if len(req.ProgramId) == 0 {
return nil, status.Error(codes.InvalidArgument, "program-id can not be 0")
}
ctx := sdk.UnwrapSDKContext(c)
program, found := k.GetProgram(ctx, req.ProgramId)
if !found {
return nil, status.Errorf(codes.NotFound, "program %s doesn't exist", req.ProgramId)
}
programFingerPrintHash := k.GetProgramFingerprintHash(&program)
return &types.QueryProgramFingerprintResponse{Fingerprint: programFingerPrintHash}, nil

Check warning on line 139 in x/bounty/keeper/grpc_query.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/grpc_query.go#L126-L139

Added lines #L126 - L139 were not covered by tests
}
54 changes: 43 additions & 11 deletions x/bounty/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (k msgServer) CreateProgram(goCtx context.Context, msg *types.MsgCreateProg
}

Check warning on line 35 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L34-L35

Added lines #L34 - L35 were not covered by tests

createTime := ctx.BlockHeader().Time
program, err := types.NewProgram(msg.ProgramId, msg.Name, msg.Detail, operatorAddr, types.ProgramStatusInactive, msg.BountyLevels, createTime)
program, err := types.NewProgram(msg.ProgramId, msg.Name, msg.Detail, operatorAddr, types.ProgramStatusInactive, createTime)
if err != nil {
return nil, err
}

Check warning on line 41 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L40-L41

Added lines #L40 - L41 were not covered by tests
Expand Down Expand Up @@ -92,9 +92,6 @@ func (k msgServer) EditProgram(goCtx context.Context, msg *types.MsgEditProgram)
if len(msg.Detail) > 0 {
program.Detail = msg.Detail
}

Check warning on line 94 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L89-L94

Added lines #L89 - L94 were not covered by tests
if len(msg.BountyLevels) > 0 {
program.BountyLevels = msg.BountyLevels
}

k.SetProgram(ctx, program)

Expand Down Expand Up @@ -166,7 +163,7 @@ func (k msgServer) CloseProgram(goCtx context.Context, msg *types.MsgCloseProgra
func (k msgServer) SubmitFinding(goCtx context.Context, msg *types.MsgSubmitFinding) (*types.MsgSubmitFindingResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

operatorAddr, err := sdk.AccAddressFromBech32(msg.SubmitterAddress)
operatorAddr, err := sdk.AccAddressFromBech32(msg.OperatorAddress)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -205,7 +202,7 @@ func (k msgServer) SubmitFinding(goCtx context.Context, msg *types.MsgSubmitFind
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.SubmitterAddress),
sdk.NewAttribute(sdk.AttributeKeySender, msg.OperatorAddress),
),
})

Expand All @@ -218,10 +215,6 @@ func (k msgServer) EditFinding(goCtx context.Context, msg *types.MsgEditFinding)
if !found {
return nil, types.ErrFindingNotExists
}

Check warning on line 217 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L212-L217

Added lines #L212 - L217 were not covered by tests
// check submitter
if finding.SubmitterAddress != msg.SubmitterAddress {
return nil, types.ErrFindingSubmitterInvalid
}
// check program
program, isExist := k.GetProgram(ctx, finding.ProgramId)
if !isExist {
Expand All @@ -231,6 +224,45 @@ func (k msgServer) EditFinding(goCtx context.Context, msg *types.MsgEditFinding)
return nil, types.ErrProgramNotActive
}

Check warning on line 225 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L219-L225

Added lines #L219 - L225 were not covered by tests

// program admin edit paymentHash
if len(msg.PaymentHash) > 0 {
// check status
if finding.Status != types.FindingStatusConfirmed {
return nil, types.ErrFindingStatusInvalid
}

Check warning on line 232 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L228-L232

Added lines #L228 - L232 were not covered by tests
// check operator is program admin
if program.AdminAddress != msg.OperatorAddress {
return nil, types.ErrFindingSubmitterInvalid
}
finding.PaymentHash = msg.PaymentHash

k.SetFinding(ctx, finding)

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeEditFindingPaymentHash,
sdk.NewAttribute(types.AttributeKeyFindingID, finding.FindingId),
sdk.NewAttribute(types.AttributeKeyProgramID, finding.ProgramId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.OperatorAddress),
),
})
return &types.MsgEditFindingResponse{}, nil

Check warning on line 253 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L234-L253

Added lines #L234 - L253 were not covered by tests
}

// whitehat edit finding
// check status
if finding.Status != types.FindingStatusSubmitted {
return nil, types.ErrFindingStatusInvalid
}

Check warning on line 260 in x/bounty/keeper/msg_server.go

View check run for this annotation

Codecov / codecov/patch

x/bounty/keeper/msg_server.go#L258-L260

Added lines #L258 - L260 were not covered by tests

// check operator is whitehat
if finding.SubmitterAddress != msg.OperatorAddress {
return nil, types.ErrFindingSubmitterInvalid
}
if len(msg.Title) > 0 {
finding.Title = msg.Title
}
Expand All @@ -255,7 +287,7 @@ func (k msgServer) EditFinding(goCtx context.Context, msg *types.MsgEditFinding)
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
sdk.NewAttribute(sdk.AttributeKeySender, msg.SubmitterAddress),
sdk.NewAttribute(sdk.AttributeKeySender, msg.OperatorAddress),
),
})

Expand Down
Loading

0 comments on commit cfc9ddf

Please sign in to comment.