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

Commit

Permalink
Merge pull request #24 from regen-network/alex/election_workflow
Browse files Browse the repository at this point in the history
Election workflow
  • Loading branch information
aaronc authored Mar 11, 2020
2 parents 9c900c4 + 914e3e4 commit bab6de6
Show file tree
Hide file tree
Showing 30 changed files with 4,572 additions and 659 deletions.
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

0 comments on commit bab6de6

Please sign in to comment.