forked from lavanet/lava
-
Notifications
You must be signed in to change notification settings - Fork 0
/
proposal_handler.go
156 lines (130 loc) · 4.69 KB
/
proposal_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package spec
import (
"fmt"
"log"
"strings"
legacyerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
sdkerrors "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
paramkeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal"
"github.com/lavanet/lava/utils"
epochstoragetypes "github.com/lavanet/lava/x/epochstorage/types"
"github.com/lavanet/lava/x/spec/keeper"
"github.com/lavanet/lava/x/spec/types"
)
// overwriting the params handler so we can add events and callbacks on specific params
// NewParamChangeProposalHandler creates a new governance Handler for a ParamChangeProposal
func NewParamChangeProposalHandler(k paramkeeper.Keeper) v1beta1.Handler {
return func(ctx sdk.Context, content v1beta1.Content) error {
switch c := content.(type) {
case *paramproposal.ParameterChangeProposal:
return HandleParameterChangeProposal(ctx, k, c)
default:
return sdkerrors.Wrapf(legacyerrors.ErrUnknownRequest, "unrecognized param proposal content type: %T", c)
}
}
}
func HandleParameterChangeProposal(ctx sdk.Context, k paramkeeper.Keeper, p *paramproposal.ParameterChangeProposal) error {
for _, c := range p.Changes {
ss, ok := k.GetSubspace(c.Subspace)
if !ok {
return sdkerrors.Wrap(paramproposal.ErrUnknownSubspace, c.Subspace)
}
logger := k.Logger(ctx)
details := []utils.Attribute{
{Key: "param", Value: c.Key},
{Key: "value", Value: c.Value},
}
if c.Key == string(epochstoragetypes.KeyLatestParamChange) {
return utils.LavaFormatWarning("Gov Proposal Param Change Error", fmt.Errorf("tried to modify "+string(epochstoragetypes.KeyLatestParamChange)),
details...,
)
}
if err := ss.Update(ctx, []byte(c.Key), []byte(c.Value)); err != nil {
return utils.LavaFormatWarning("Gov Proposal Param Change Error", fmt.Errorf("tried to modify %s: %w", c.Key, err),
details...,
)
}
details = append(details, utils.Attribute{Key: epochstoragetypes.ModuleName, Value: ctx.BlockHeight()})
detailsMap := map[string]string{}
for _, atr := range details {
detailsMap[atr.Key] = fmt.Sprint(atr.Value)
}
utils.LogLavaEvent(ctx, logger, types.ParamChangeEventName, detailsMap, "Gov Proposal Accepted Param Changed")
}
ss, ok := k.GetSubspace(epochstoragetypes.ModuleName)
if !ok {
return sdkerrors.Wrap(paramproposal.ErrUnknownSubspace, epochstoragetypes.ModuleName)
}
ss.Set(ctx, epochstoragetypes.KeyLatestParamChange, uint64(ctx.BlockHeight())) // set the LatestParamChange
return nil
}
// NewSpecProposalsHandler creates a new governance Handler for a Spec
func NewSpecProposalsHandler(k keeper.Keeper) v1beta1.Handler {
return func(ctx sdk.Context, content v1beta1.Content) error {
switch c := content.(type) {
case *types.SpecAddProposal:
return handleSpecProposal(ctx, k, c)
default:
log.Println("unrecognized spec proposal content")
return sdkerrors.Wrapf(legacyerrors.ErrUnknownRequest, "unrecognized spec proposal content type: %T", c)
}
}
}
func handleSpecProposal(ctx sdk.Context, k keeper.Keeper, p *types.SpecAddProposal) error {
logger := k.Logger(ctx)
type event struct {
name string
event string
details map[string]string
}
var events []event
for _, spec := range p.Specs {
_, found := k.GetSpec(ctx, spec.Index)
spec.BlockLastUpdated = uint64(ctx.BlockHeight())
k.SetSpec(ctx, spec)
details, err := k.ValidateSpec(ctx, spec)
if err != nil {
attrs := utils.StringMapToAttributes(details)
return utils.LavaFormatWarning("invalid spec", err, attrs...)
}
name := types.SpecAddEventName
if found {
name = types.SpecModifyEventName
}
// collect the events first, and only log them after everything succeeded
events = append(events, event{
name: name,
event: "Gov Proposal Accepted Spec",
details: details,
})
// TODO: add api types once its implemented to the event
}
// re-validate all the specs, in case the modified spec is imported by
// other specs and the new version creates a conflict; also update the
// BlockLastUpdated of all specs that inherit from the modified spec.
for _, spec := range k.GetAllSpec(ctx) {
inherits, err := k.RefreshSpec(ctx, spec, p.Specs)
if err != nil {
return utils.LavaFormatWarning("invalidated spec", err)
}
if len(inherits) > 0 {
details := map[string]string{
"name": spec.Index,
"import": strings.Join(inherits, ","),
}
name := types.SpecRefreshEventName
events = append(events, event{
name: name,
event: "Gov Proposal Refreshsed Spec",
details: details,
})
}
}
for _, e := range events {
utils.LogLavaEvent(ctx, logger, e.name, e.details, e.event)
}
return nil
}