Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

Election workflow #24

Merged
merged 16 commits into from
Mar 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion incubator/group/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,19 @@ func NewCodec(amino *codec.Codec) *Codec {
// RegisterCodec registers all the necessary crisis module concrete types and
// interfaces with the provided codec reference.
func RegisterCodec(cdc *codec.Codec) {
cdc.RegisterConcrete(MsgCreateGroup{}, "ccosmos-sdk/MsgCreateGroup", nil)
cdc.RegisterConcrete(MsgCreateGroup{}, "cosmos-sdk/MsgCreateGroup", nil)
cdc.RegisterConcrete(MsgUpdateGroupMembers{}, "cosmos-sdk/MsgUpdateGroupMembers", nil)
cdc.RegisterConcrete(MsgUpdateGroupAdmin{}, "cosmos-sdk/MsgUpdateGroupAdmin", nil)
cdc.RegisterConcrete(MsgUpdateGroupComment{}, "cosmos-sdk/MsgUpdateGroupComment", nil)
cdc.RegisterConcrete(MsgCreateGroupAccountStd{}, "cosmos-sdk/MsgCreateGroupAccountStd", nil)
cdc.RegisterConcrete(MsgVote{}, "cosmos-sdk/group/MsgVote", nil)
cdc.RegisterConcrete(MsgExec{}, "cosmos-sdk/group/MsgExec", nil)

// oh man... amino
cdc.RegisterConcrete(StdDecisionPolicy{}, "cosmos-sdk/StdDecisionPolicy", nil)
cdc.RegisterConcrete(&StdDecisionPolicy_Threshold{}, "cosmos-sdk/StdDecisionPolicy_Threshold", nil)
cdc.RegisterConcrete(ThresholdDecisionPolicy{}, "cosmos-sdk/ThresholdDecisionPolicy", nil)
cdc.RegisterInterface((*isStdDecisionPolicy_Sum)(nil), nil)
}

// generic sealed codec to be used throughout module
Expand Down
126 changes: 126 additions & 0 deletions incubator/group/conditions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package group

import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"regexp"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/errors"
)

var (
// AddressLength is the length of all addresses
// You can modify it in init() before any addresses are calculated,
// but it must not change during the lifetime of the kvstore
AddressLength = 20

// it must have (?s) flags, otherwise it errors when last section contains 0x20 (newline)
perm = regexp.MustCompile(`(?s)^([a-zA-Z0-9_\-]{3,8})/([a-zA-Z0-9_\-]{3,8})/(.+)$`)
)

// Condition is a specially formatted array, containing
// information on who can authorize an action.
// It is of the format:
//
// sprintf("%s/%s/%s", extension, type, data)
type Condition []byte

func NewCondition(ext, typ string, data []byte) Condition {
pre := fmt.Sprintf("%s/%s/", ext, typ)
return append([]byte(pre), data...)
}

// Parse will extract the sections from the Condition bytes
// and verify it is properly formatted
func (c Condition) Parse() (string, string, []byte, error) {
chunks := perm.FindSubmatch(c)
if len(chunks) == 0 {
return "", "", nil, errors.Wrapf(ErrInvalid, "condition: %X", []byte(c))

}
// returns [all, match1, match2, match3]
return string(chunks[1]), string(chunks[2]), chunks[3], nil
}

// Address will convert a Condition into an Address
func (c Condition) Address() sdk.AccAddress {
return newAddress(c)
}

// Equals checks if two permissions are the same
func (a Condition) Equals(b Condition) bool {
return bytes.Equal(a, b)
}

// String returns a human readable string.
// We keep the extension and type in ascii and
// hex-encode the binary data
func (c Condition) String() string {
ext, typ, data, err := c.Parse()
if err != nil {
return fmt.Sprintf("Invalid Condition: %X", []byte(c))
}
return fmt.Sprintf("%s/%s/%X", ext, typ, data)
}

// Validate returns an error if the Condition is not the proper format
func (c Condition) Validate() error {
if len(c) == 0 {
return ErrEmpty
}
if !perm.Match(c) {
return errors.Wrapf(ErrInvalid, "condition: %X", []byte(c))
}
return nil
}

func (c Condition) MarshalJSON() ([]byte, error) {
var serialized string
if c != nil {
serialized = c.String()
}
return json.Marshal(serialized)
}

func (c *Condition) UnmarshalJSON(raw []byte) error {
var enc string
if err := json.Unmarshal(raw, &enc); err != nil {
return errors.Wrap(err, "cannot decode json")
}
return c.deserialize(enc)
}

// deserialize from human readable string.
func (c *Condition) deserialize(source string) error {
// No value zero the address.
if len(source) == 0 {
*c = nil
return nil
}

args := strings.Split(source, "/")
if len(args) != 3 {
return errors.Wrap(ErrInvalid, "invalid condition format")
}
data, err := hex.DecodeString(args[2])
if err != nil {
return errors.Wrapf(ErrInvalid, "malformed condition data: %s", err)
}
*c = NewCondition(args[0], args[1], data)
return nil
}

// newAddress hashes and truncates into the proper size
func newAddress(data []byte) sdk.AccAddress {
if data == nil {
return nil
}
// h := blake2b.Sum256(data)
h := sha256.Sum256(data)
return h[:sdk.AddrLen]
}
71 changes: 71 additions & 0 deletions incubator/group/conditions_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package group_test

import (
"encoding/json"
"testing"

"github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/modules/incubator/group"
"github.com/stretchr/testify/assert"
)

func TestConditionUnmarshalJSON(t *testing.T) {
cases := map[string]struct {
json string
wantErr *errors.Error
wantCondition group.Condition
}{
"default decoding": {
json: `"foo/bar/636f6e646974696f6e64617461"`,
wantCondition: group.NewCondition("foo", "bar", []byte("conditiondata")),
},
"invalid condition format": {
json: `"foo/636f6e646974696f6e64617461"`,
wantErr: group.ErrInvalid,
},
"invalid condition data": {
json: `"foo/bar/zzzzz"`,
wantErr: group.ErrInvalid,
},
"zero address": {
json: `""`,
wantCondition: nil,
},
}

for testName, tc := range cases {
t.Run(testName, func(t *testing.T) {
var got group.Condition
err := json.Unmarshal([]byte(tc.json), &got)
if !tc.wantErr.Is(err) {
t.Fatalf("got error: %+v", err)
}
if err == nil && !got.Equals(tc.wantCondition) {
t.Fatalf("expected %q but got condition: %q", tc.wantCondition, got)
}
})
}
}

func TestConditionMarshalJSON(t *testing.T) {
cases := map[string]struct {
source group.Condition
wantJson string
}{
"cond encoding": {
source: group.NewCondition("foo", "bar", []byte("conditiondata")),
wantJson: `"foo/bar/636F6E646974696F6E64617461"`,
},
"nil encoding": {
source: nil,
wantJson: `""`,
},
}
for testName, tc := range cases {
t.Run(testName, func(t *testing.T) {
got, err := json.Marshal(tc.source)
assert.Nil(t, err)
assert.Equal(t, tc.wantJson, string(got))
})
}
}
13 changes: 8 additions & 5 deletions incubator/group/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package group
import sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

var (
ErrEmpty = sdkerrors.Register(ModuleName, 1, "value is empty")
ErrDuplicate = sdkerrors.Register(ModuleName, 2, "duplicate value")
ErrMaxLimit = sdkerrors.Register(ModuleName, 3, "limit exceeded")
ErrType = sdkerrors.Register(ModuleName, 4, "invalid type")
ErrInvalid = sdkerrors.Register(ModuleName, 5, "invalid value")
ErrEmpty = sdkerrors.Register(ModuleName, 1, "value is empty")
ErrDuplicate = sdkerrors.Register(ModuleName, 2, "duplicate value")
ErrMaxLimit = sdkerrors.Register(ModuleName, 3, "limit exceeded")
ErrType = sdkerrors.Register(ModuleName, 4, "invalid type")
ErrInvalid = sdkerrors.Register(ModuleName, 5, "invalid value")
ErrUnauthorized = sdkerrors.Register(ModuleName, 6, "unauthorized")
ErrModified = sdkerrors.Register(ModuleName, 7, "modified")
ErrExpired = sdkerrors.Register(ModuleName, 8, "expired")
)
13 changes: 4 additions & 9 deletions incubator/group/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,9 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

// GenesisState is the state that must be provided at genesis.
type GenesisState struct {
Params Params `json:"params" yaml:"params"`
}

// NewGenesisState creates a new genesis state with default values.
func NewGenesisState() GenesisState {
return GenesisState{
func NewGenesisState() *GenesisState {
return &GenesisState{
Params: DefaultParams(),
}
}
Expand All @@ -21,8 +16,8 @@ func (s GenesisState) Validate() error {
}

// ExportGenesis returns a GenesisState for a given context and Keeper.
func ExportGenesis(ctx sdk.Context, k Keeper) GenesisState {
return GenesisState{
func ExportGenesis(ctx sdk.Context, k Keeper) *GenesisState {
return &GenesisState{
Params: k.getParams(ctx),
}
}
1 change: 1 addition & 0 deletions incubator/group/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/gogo/protobuf v1.3.1
github.com/gorilla/mux v1.7.3
github.com/pkg/errors v0.9.1
github.com/regen-network/cosmos-proto v0.1.1-0.20200213154359-02baa11ea7c2
github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.4.0
github.com/tendermint/tendermint v0.33.0
Expand Down
3 changes: 3 additions & 0 deletions incubator/group/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ github.com/golang/mock v1.3.1-0.20190508161146-9fa652df1129/go.mod h1:sBzyDLLjw3
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
Expand Down Expand Up @@ -210,6 +211,8 @@ github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFE
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/regen-network/cosmos-proto v0.1.0 h1:gsV+YO2kMvY430zQn8ioPXRxEJgb/ms0iMPeWo3VEyY=
github.com/regen-network/cosmos-proto v0.1.0/go.mod h1:+r7jN10xXCypD4yBgzKOa+vgLz0riqYMHeDcKekxPvA=
github.com/regen-network/cosmos-proto v0.1.1-0.20200213154359-02baa11ea7c2 h1:jQK1YoH972Aptd22YKgtNu5jM2X2xMGkyIENOAc71to=
github.com/regen-network/cosmos-proto v0.1.1-0.20200213154359-02baa11ea7c2/go.mod h1:+r7jN10xXCypD4yBgzKOa+vgLz0riqYMHeDcKekxPvA=
github.com/regen-network/protobuf v1.3.2-alpha.regen.1 h1:YdeZbBS0lG1D13COb7b57+nM/RGgIs8WF9DwitU6EBM=
github.com/regen-network/protobuf v1.3.2-alpha.regen.1/go.mod h1:lye6mqhOn/GCw1zRl3uPD5VP8rC+LPMyTyPAyQV872U=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
Expand Down
Loading