diff --git a/crypto/keys/bls12381/bls12381.go b/crypto/keys/bls12381/bls12381.go index eab266c3d2..7aa9ffb98c 100644 --- a/crypto/keys/bls12381/bls12381.go +++ b/crypto/keys/bls12381/bls12381.go @@ -122,7 +122,7 @@ func genPrivKey(rand io.Reader) []byte { sk := blst.KeyGen(ikm[:]) if sk == nil { - panic("Failed to generate secret key!") + panic("failed to generate secret key!") } skBytes := sk.Serialize() @@ -136,7 +136,12 @@ func genPrivKey(rand io.Reader) []byte { // if it's derived from user input. func GenPrivKeyFromSecret(secret []byte) *PrivKey { ikm := crypto.Sha256(secret) // Not Ripemd160 because we want 32 bytes. - skBytes := blst.KeyGen(ikm).Serialize() + + sk := blst.KeyGen(ikm) + if sk == nil { + panic("failed to generate secret key from ikm") + } + skBytes := sk.Serialize() return &PrivKey{Key: skBytes} } diff --git a/crypto/keys/bls12381/bls12381_test.go b/crypto/keys/bls12381/bls12381_test.go index 48fbd02faf..558dbd7c5f 100644 --- a/crypto/keys/bls12381/bls12381_test.go +++ b/crypto/keys/bls12381/bls12381_test.go @@ -1,12 +1,20 @@ package bls12381_test import ( + "encoding/base64" + "testing" + + "github.com/cosmos/cosmos-sdk/codec/types" + cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" + + "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" bench "github.com/cosmos/cosmos-sdk/crypto/keys/internal/benchmarking" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto" - "testing" ) func TestSignAndValidateBls12381(t *testing.T) { @@ -22,6 +30,166 @@ func TestSignAndValidateBls12381(t *testing.T) { } +func TestKeyFromSecret(t *testing.T) { + insecureSeed := []byte("a random number for testing") + privKey := bls12381.GenPrivKeyFromSecret(insecureSeed) + pubKey := privKey.PubKey() + + msg := []byte("hello") + sig, err := privKey.Sign(msg) + require.Nil(t, err) + assert.True(t, pubKey.VerifySignature(msg, sig)) +} + +func TestPubKeyEquals(t *testing.T) { + bls12381PubKey := bls12381.GenPrivKey().PubKey().(*bls12381.PubKey) + + testCases := []struct { + msg string + pubKey cryptotypes.PubKey + other cryptotypes.PubKey + expectEq bool + }{ + { + "different bytes", + bls12381PubKey, + bls12381.GenPrivKey().PubKey(), + false, + }, + { + "equals", + bls12381PubKey, + &bls12381.PubKey{ + Key: bls12381PubKey.Key, + }, + true, + }, + { + "different types", + bls12381PubKey, + secp256k1.GenPrivKey().PubKey(), + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.msg, func(t *testing.T) { + eq := tc.pubKey.Equals(tc.other) + require.Equal(t, eq, tc.expectEq) + }) + } +} + +func TestPrivKeyEquals(t *testing.T) { + bls12381PrivKey := bls12381.GenPrivKey() + + testCases := []struct { + msg string + privKey cryptotypes.PrivKey + other cryptotypes.PrivKey + expectEq bool + }{ + { + "different bytes", + bls12381PrivKey, + bls12381.GenPrivKey(), + false, + }, + { + "equals", + bls12381PrivKey, + &bls12381.PrivKey{ + Key: bls12381PrivKey.Key, + }, + true, + }, + { + "different types", + bls12381PrivKey, + secp256k1.GenPrivKey(), + false, + }, + } + + for _, tc := range testCases { + t.Run(tc.msg, func(t *testing.T) { + eq := tc.privKey.Equals(tc.other) + require.Equal(t, eq, tc.expectEq) + }) + } +} + +func TestMarshalAmino(t *testing.T) { + aminoCdc := codec.NewLegacyAmino() + privKey := bls12381.GenPrivKey() + pubKey := privKey.PubKey().(*bls12381.PubKey) + + testCases := []struct { + desc string + msg codec.AminoMarshaler + typ interface{} + expBinary []byte + expJSON string + }{ + { + "bls12381 private key", + privKey, + &bls12381.PrivKey{}, + append([]byte{32}, privKey.Bytes()...), // Length-prefixed. + "\"" + base64.StdEncoding.EncodeToString(privKey.Bytes()) + "\"", + }, + { + "bls12381 public key", + pubKey, + &bls12381.PubKey{}, + append([]byte{96}, pubKey.Bytes()...), // Length-prefixed. + "\"" + base64.StdEncoding.EncodeToString(pubKey.Bytes()) + "\"", + }, + } + + for _, tc := range testCases { + t.Run(tc.desc, func(t *testing.T) { + // Do a round trip of encoding/decoding binary. + bz, err := aminoCdc.Marshal(tc.msg) + require.NoError(t, err) + require.Equal(t, tc.expBinary, bz) + + err = aminoCdc.Unmarshal(bz, tc.typ) + require.NoError(t, err) + + require.Equal(t, tc.msg, tc.typ) + + // Do a round trip of encoding/decoding JSON. + bz, err = aminoCdc.MarshalJSON(tc.msg) + require.NoError(t, err) + require.Equal(t, tc.expJSON, string(bz)) + + err = aminoCdc.UnmarshalJSON(bz, tc.typ) + require.NoError(t, err) + + require.Equal(t, tc.msg, tc.typ) + }) + } +} + +func TestMarshalJSON(t *testing.T) { + require := require.New(t) + privKey := bls12381.GenPrivKey() + pk := privKey.PubKey() + + registry := types.NewInterfaceRegistry() + cryptocodec.RegisterInterfaces(registry) + cdc := codec.NewProtoCodec(registry) + + bz, err := cdc.MarshalInterfaceJSON(pk) + require.NoError(err) + + var pk2 cryptotypes.PubKey + err = cdc.UnmarshalInterfaceJSON(bz, &pk2) + require.NoError(err) + require.True(pk2.Equals(pk)) +} + func BenchmarkSignBls(b *testing.B) { privKey := bls12381.GenPrivKey() diff --git a/crypto/keys/bls12381/multisig.go b/crypto/keys/bls12381/multisig.go index 18e499e390..e7a854c463 100644 --- a/crypto/keys/bls12381/multisig.go +++ b/crypto/keys/bls12381/multisig.go @@ -47,7 +47,7 @@ func AggregateSignature(sigs [][]byte) ([]byte, error) { // VerifyMultiSignature assumes public key is already validated func VerifyMultiSignature(msg []byte, sig []byte, pks []*PubKey) error { - return VerifyAggregateSignature([][]byte{msg}, sig, [][]*PubKey{pks}) + return VerifyAggregateSignature([][]byte{msg}, false, sig, [][]*PubKey{pks}) } func Unique(msgs [][]byte) bool { @@ -65,18 +65,32 @@ func Unique(msgs [][]byte) bool { return true } -func VerifyAggregateSignature(msgs [][]byte, sig []byte, pkss [][]*PubKey) error { +func VerifyAggregateSignature(msgs [][]byte, msgCheck bool, sig []byte, pkss [][]*PubKey) error { n := len(msgs) if n == 0 { return fmt.Errorf("messages cannot be empty") } + for i, msg := range msgs { + if len(msg) == 0 { + return fmt.Errorf("%d-th message is empty", i) + } + } + if len(pkss) != n { return fmt.Errorf("the number of messages and public key sets must match") } - if !Unique(msgs) { - return fmt.Errorf("messages must be pairwise distinct") + for i, pks := range pkss { + if len(pks) == 0 { + return fmt.Errorf("%d-th public key set is empty", i) + } + } + + if msgCheck { + if !Unique(msgs) { + return fmt.Errorf("messages must be pairwise distinct") + } } apks := make([]*blst.P1Affine, len(pkss)) diff --git a/crypto/keys/bls12381/multisig_test.go b/crypto/keys/bls12381/multisig_test.go index c0024f859b..20168ee4cc 100644 --- a/crypto/keys/bls12381/multisig_test.go +++ b/crypto/keys/bls12381/multisig_test.go @@ -55,8 +55,7 @@ func TestBlsAggSig(t *testing.T) { aggSig, err := bls.AggregateSignature(sigs) require.Nil(t, err) - assert.Nil(t, bls.VerifyAggregateSignature(msgs, aggSig, pks)) - + assert.Nil(t, bls.VerifyAggregateSignature(msgs, true, aggSig, pks)) } func benchmarkBlsVerifyMulti(total int, b *testing.B) { @@ -113,7 +112,7 @@ func benchmarkBlsVerifyAgg(total int, b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - bls.VerifyAggregateSignature(msgs, aggSig, pks) + bls.VerifyAggregateSignature(msgs, false, aggSig, pks) } } diff --git a/crypto/keys/ed25519/ed25519_test.go b/crypto/keys/ed25519/ed25519_test.go index 4bde85a1dc..97bb3ea5b7 100644 --- a/crypto/keys/ed25519/ed25519_test.go +++ b/crypto/keys/ed25519/ed25519_test.go @@ -3,9 +3,8 @@ package ed25519_test import ( stded25519 "crypto/ed25519" "encoding/base64" - "testing" - bench "github.com/cosmos/cosmos-sdk/crypto/keys/internal/benchmarking" + "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" diff --git a/go.mod b/go.mod index c3a41b2c2b..870e01ab43 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/bgentry/speakeasy v0.1.0 github.com/btcsuite/btcd v0.22.0-beta github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce + github.com/cockroachdb/apd/v2 v2.0.2 github.com/coinbase/rosetta-sdk-go v0.6.10 github.com/confio/ics23/go v0.6.6 github.com/cosmos/go-bip39 v1.0.0 @@ -27,6 +28,7 @@ require ( github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 github.com/improbable-eng/grpc-web v0.14.0 github.com/jhump/protoreflect v1.8.2 + github.com/lib/pq v1.10.2 // indirect github.com/magiconair/properties v1.8.5 github.com/mattn/go-isatty v0.0.13 github.com/otiai10/copy v1.6.0 @@ -41,18 +43,19 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.8.0 github.com/stretchr/testify v1.7.0 - github.com/supranational/blst v0.3.4 + github.com/supranational/blst v0.3.5 github.com/tendermint/btcd v0.1.1 github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 github.com/tendermint/go-amino v0.16.0 github.com/tendermint/tendermint v0.34.11 github.com/tendermint/tm-db v0.6.4 - golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c google.golang.org/grpc v1.38.0 google.golang.org/protobuf v1.26.0 gopkg.in/yaml.v2 v2.4.0 nhooyr.io/websocket v1.8.6 // indirect + pgregory.net/rapid v0.4.7 ) replace google.golang.org/grpc => google.golang.org/grpc v1.33.2 diff --git a/go.sum b/go.sum index e273deeaf1..02fb6fe25c 100644 --- a/go.sum +++ b/go.sum @@ -139,6 +139,8 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/apd/v2 v2.0.2/go.mod h1:DDxRlzC2lo3/vSlmSoS7JkqbbrARPuFOGr0B9pvN3Gw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coinbase/rosetta-sdk-go v0.6.10 h1:rgHD/nHjxLh0lMEdfGDqpTtlvtSBwULqrrZ2qPdNaCM= @@ -480,6 +482,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= @@ -725,8 +729,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/supranational/blst v0.3.4 h1:iZE9lBMoywK2uy2U/5hDOvobQk9FnOQ2wNlu9GmRCoA= -github.com/supranational/blst v0.3.4/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/supranational/blst v0.3.5 h1:/pey7U712GgJBSD1XTiJ5iBqjYIH3QNdrjRoGXlJJ60= +github.com/supranational/blst v0.3.5/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= @@ -817,8 +821,8 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -997,8 +1001,9 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1212,6 +1217,8 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/proto/regen/group/v1alpha1/events.proto b/proto/regen/group/v1alpha1/events.proto new file mode 100644 index 0000000000..3b0d1c30cf --- /dev/null +++ b/proto/regen/group/v1alpha1/events.proto @@ -0,0 +1,68 @@ +syntax = "proto3"; + +package regen.group.v1alpha1; + +option go_package = "github.com/cosmos/cosmos-sdk/x/group"; + +// EventCreateGroup is an event emitted when a group is created. +message EventCreateGroup { + + // group_id is the unique ID of the group. + uint64 group_id = 1; +} + +// EventUpdateGroup is an event emitted when a group is updated. +message EventUpdateGroup { + + // group_id is the unique ID of the group. + uint64 group_id = 1; +} + +// EventCreateGroupAccount is an event emitted when a group account is created. +message EventCreateGroupAccount { + + // address is the address of the group account. + string address = 1; +} + +// EventUpdateGroupAccount is an event emitted when a group account is updated. +message EventUpdateGroupAccount { + + // address is the address of the group account. + string address = 1; +} + +// EventCreateProposal is an event emitted when a proposal is created. +message EventCreateProposal { + + // proposal_id is the unique ID of the proposal. + uint64 proposal_id = 1; +} + +// EventVote is an event emitted when a voter votes on a proposal. +message EventVote { + + // proposal_id is the unique ID of the proposal. + uint64 proposal_id = 1; +} + +// EventExec is an event emitted when a proposal is executed. +message EventExec { + + // proposal_id is the unique ID of the proposal. + uint64 proposal_id = 1; +} + +// EventCreateProposal is an event emitted when a proposal is created. +message EventCreatePoll { + + // poll_id is the unique ID of the poll. + uint64 poll_id = 1; +} + +// EventVotePoll is an event emitted when a voter votes on a proposal. +message EventVotePoll { + + // poll_id is the unique ID of the proposal. + uint64 poll_id = 1; +} \ No newline at end of file diff --git a/proto/regen/group/v1alpha1/genesis.proto b/proto/regen/group/v1alpha1/genesis.proto new file mode 100644 index 0000000000..b5ac744c13 --- /dev/null +++ b/proto/regen/group/v1alpha1/genesis.proto @@ -0,0 +1,49 @@ +syntax = "proto3"; + +package regen.group.v1alpha1; + +option go_package = "github.com/cosmos/cosmos-sdk/x/group"; + +import "gogoproto/gogo.proto"; +import "regen/group/v1alpha1/types.proto"; + +// GenesisState defines the group module's genesis state. +message GenesisState { + + // group_seq is the group table orm.Sequence, + // it is used to get the next group ID. + uint64 group_seq = 1; + + // groups is the list of groups info. + repeated GroupInfo groups = 2; + + // group_members is the list of groups members. + repeated GroupMember group_members = 3; + + // group_account_seq is the group account table orm.Sequence, + // it is used to generate the next group account address. + uint64 group_account_seq = 4; + + // group_accounts is the list of group accounts info. + repeated GroupAccountInfo group_accounts = 5; + + // proposal_seq is the proposal table orm.Sequence, + // it is used to get the next proposal ID. + uint64 proposal_seq = 6; + + // proposals is the list of proposals. + repeated Proposal proposals = 7; + + // votes is the list of votes. + repeated Vote votes = 8; + + // polls is the list of polls. + repeated Poll polls = 9; + + // poll_seq is the poll table orm.Sequence, + // it is used to get the next poll ID. + uint64 poll_seq = 10; + + // votes is the list of votes for poll. + repeated VotePoll votes_for_poll = 11; +} diff --git a/proto/regen/group/v1alpha1/query.proto b/proto/regen/group/v1alpha1/query.proto new file mode 100644 index 0000000000..ad0e410a35 --- /dev/null +++ b/proto/regen/group/v1alpha1/query.proto @@ -0,0 +1,407 @@ +syntax = "proto3"; + +package regen.group.v1alpha1; + +import "regen/group/v1alpha1/types.proto"; +import "google/api/annotations.proto"; +import "gogoproto/gogo.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/group"; + +// Query is the regen.group.v1alpha1 Query service. +service Query { + + // GroupInfo queries group info based on group id. + rpc GroupInfo(QueryGroupInfoRequest) returns (QueryGroupInfoResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/groups/{group_id}/info"; + } + + // GroupAccountInfo queries group account info based on group account address. + rpc GroupAccountInfo(QueryGroupAccountInfoRequest) returns (QueryGroupAccountInfoResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/groups/accounts/{address}"; + } + // GroupMembers queries members of a group + rpc GroupMembers(QueryGroupMembersRequest) returns (QueryGroupMembersResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/groups/{group_id}/members"; + } + + // GroupsByAdmin queries groups by admin address. + rpc GroupsByAdmin(QueryGroupsByAdminRequest) returns (QueryGroupsByAdminResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/groups/admins/{admin}"; + } + + // GroupAccountsByGroup queries group accounts by group id. + rpc GroupAccountsByGroup(QueryGroupAccountsByGroupRequest) returns (QueryGroupAccountsByGroupResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/groups/{group_id}/accounts"; + } + + // GroupsByAdmin queries group accounts by admin address. + rpc GroupAccountsByAdmin(QueryGroupAccountsByAdminRequest) returns (QueryGroupAccountsByAdminResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/admins/{admin}/accounts"; + } + + // Proposal queries a proposal based on proposal id. + rpc Proposal(QueryProposalRequest) returns (QueryProposalResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/proposals/{proposal_id}"; + } + + // ProposalsByGroupAccount queries proposals based on group account address. + rpc ProposalsByGroupAccount(QueryProposalsByGroupAccountRequest) returns (QueryProposalsByGroupAccountResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/group-accounts/{address}/proposals"; + } + + // VoteByProposalVoter queries a vote by proposal id and voter. + rpc VoteByProposalVoter(QueryVoteByProposalVoterRequest) returns (QueryVoteByProposalVoterResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/proposals/{proposal_id}/votes/{voter}"; + } + + // VotesByProposal queries a vote by proposal. + rpc VotesByProposal(QueryVotesByProposalRequest) returns (QueryVotesByProposalResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/proposals/{proposal_id}/votes"; + } + + // VotesByVoter queries a vote by voter. + rpc VotesByVoter(QueryVotesByVoterRequest) returns (QueryVotesByVoterResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/voters/{voter}"; + } + + // Poll queries a poll based on poll id. + rpc Poll(QueryPollRequest) returns (QueryPollResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/polls/{poll_id}"; + } + + // PollsByGroup queries polls based on group id. + rpc PollsByGroup(QueryPollsByGroupRequest) returns (QueryPollsByGroupResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/group/polls"; + } + + // PollsByCreator queries polls by creator address. + rpc PollsByCreator(QueryPollsByCreatorRequest) returns (QueryPollsByCreatorResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/creators/{creator}/polls"; + } + + // VoteForPollByPollVoter queries a vote by poll id and voter. + rpc VoteForPollByPollVoter(QueryVoteForPollByPollVoterRequest) returns (QueryVoteForPollByPollVoterResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/polls/{poll_id}/votes/{voter}"; + } + + // VotesForPollByPoll queries votes by poll. + rpc VotesForPollByPoll(QueryVotesForPollByPollRequest) returns (QueryVotesForPollByPollResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/polls/{poll_id}/votes"; + } + + // VotesForPollByVoter queries votes for poll by voter. + rpc VotesForPollByVoter(QueryVotesForPollByVoterRequest) returns (QueryVotesForPollByVoterResponse) { + option (google.api.http).get = "/regen/group/v1alpha1/voters/{voter}"; + } +} + +// QueryGroupInfoRequest is the Query/GroupInfo request type. +message QueryGroupInfoRequest { + + // group_id is the unique ID of the group. + uint64 group_id = 1; +} + +// QueryGroupInfoResponse is the Query/GroupInfo response type. +message QueryGroupInfoResponse { + + // info is the GroupInfo for the group. + GroupInfo info = 1; +} + +// QueryGroupAccountInfoRequest is the Query/GroupAccountInfo request type. +message QueryGroupAccountInfoRequest { + + // address is the account address of the group account. + string address = 1; +} + +// QueryGroupAccountInfoResponse is the Query/GroupAccountInfo response type. +message QueryGroupAccountInfoResponse { + + // info is the GroupAccountInfo for the group account. + GroupAccountInfo info = 1; +} + +// QueryGroupMembersRequest is the Query/GroupMembersRequest request type. +message QueryGroupMembersRequest { + + // group_id is the unique ID of the group. + uint64 group_id = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryGroupMembersResponse is the Query/GroupMembersResponse response type. +message QueryGroupMembersResponse { + + // members are the members of the group with given group_id. + repeated GroupMember members = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryGroupsByAdminRequest is the Query/GroupsByAdminRequest request type. +message QueryGroupsByAdminRequest { + + // admin is the account address of a group's admin. + string admin = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryGroupsByAdminResponse is the Query/GroupsByAdminResponse response type. +message QueryGroupsByAdminResponse { + + // groups are the groups info with the provided admin. + repeated GroupInfo groups = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryGroupAccountsByGroupRequest is the Query/GroupAccountsByGroup request type. +message QueryGroupAccountsByGroupRequest { + + // group_id is the unique ID of the group account's group. + uint64 group_id = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryGroupAccountsByGroupResponse is the Query/GroupAccountsByGroup response type. +message QueryGroupAccountsByGroupResponse { + + // group_accounts are the group accounts info associated with the provided group. + repeated GroupAccountInfo group_accounts = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryGroupAccountsByAdminRequest is the Query/GroupAccountsByAdmin request type. +message QueryGroupAccountsByAdminRequest { + + // admin is the admin address of the group account. + string admin = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryGroupAccountsByAdminResponse is the Query/GroupAccountsByAdmin response type. +message QueryGroupAccountsByAdminResponse { + + // group_accounts are the group accounts info with provided admin. + repeated GroupAccountInfo group_accounts = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryProposalRequest is the Query/Proposal request type. +message QueryProposalRequest { + + // proposal_id is the unique ID of a proposal. + uint64 proposal_id = 1; +} + +// QueryProposalResponse is the Query/Proposal response type. +message QueryProposalResponse { + + // proposal is the proposal info. + Proposal proposal = 1; +} + +// QueryProposalsByGroupAccountRequest is the Query/ProposalByGroupAccount request type. +message QueryProposalsByGroupAccountRequest { + + // address is the group account address related to proposals. + string address = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryProposalsByGroupAccountResponse is the Query/ProposalByGroupAccount response type. +message QueryProposalsByGroupAccountResponse { + + // proposals are the proposals with given group account. + repeated Proposal proposals = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryVoteByProposalVoterResponse is the Query/VoteByProposalVoter request type. +message QueryVoteByProposalVoterRequest { + + // proposal_id is the unique ID of a proposal. + uint64 proposal_id = 1; + + // voter is a proposal voter account address. + string voter = 2; +} + +// QueryVoteByProposalVoterResponse is the Query/VoteByProposalVoter response type. +message QueryVoteByProposalVoterResponse { + + // vote is the vote with given proposal_id and voter. + Vote vote = 1; +} + +// QueryVotesByProposalResponse is the Query/VotesByProposal request type. +message QueryVotesByProposalRequest { + + // proposal_id is the unique ID of a proposal. + uint64 proposal_id = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryVotesByProposalResponse is the Query/VotesByProposal response type. +message QueryVotesByProposalResponse { + + // votes are the list of votes for given proposal_id. + repeated Vote votes = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryVotesByVoterResponse is the Query/VotesByVoter request type. +message QueryVotesByVoterRequest { + // voter is a proposal voter account address. + string voter = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryVotesByVoterResponse is the Query/VotesByVoter response type. +message QueryVotesByVoterResponse { + + // votes are the list of votes by given voter. + repeated Vote votes = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + + +// QueryPollRequest is the Query/Poll request type. +message QueryPollRequest { + + // poll_id is the unique ID of a poll. + uint64 poll_id = 1; +} + +// QueryPollResponse is the Query/Poll response type. +message QueryPollResponse { + + // poll is the poll info. + Poll poll = 1; +} + +// QueryPollsByGroupRequest is the Query/PollByGroup request type. +message QueryPollsByGroupRequest { + + // group_id is the group id related to polls. + uint64 group_id = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryPollsByGroupResponse is the Query/PollByGroup response type. +message QueryPollsByGroupResponse { + + // polls are the polls with given group id. + repeated Poll polls = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryPollsByCreatorRequest is the Query/PollByCreator request type. +message QueryPollsByCreatorRequest { + + // creator is the creator address related to polls. + string creator = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryPollsByCreatorResponse is the Query/PollsByCreator response type. +message QueryPollsByCreatorResponse { + + // polls are the polls with given creator. + repeated Poll polls = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryVoteForPollByPollVoterRequest is the Query/VotePollByPollVoter request type. +message QueryVoteForPollByPollVoterRequest { + + // poll_id is the unique ID of a poll. + uint64 poll_id = 1; + + // voter is a poll voter account address. + string voter = 2; +} + +// QueryVotesForPollByPollVoterResponse is the Query/VotePollByPollVoter response type. +message QueryVoteForPollByPollVoterResponse { + + // vote is the vote with given poll_id and voter. + VotePoll vote = 1; +} + +// QueryVotesForPollByPollRequest is the Query/VotePollsByPoll request type. +message QueryVotesForPollByPollRequest { + + // poll_id is the unique ID of a poll. + uint64 poll_id = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryVotesForPollByPollResponse is the Query/VotePollsByPoll response type. +message QueryVotesForPollByPollResponse { + + // votes are the list of votes for given poll_id. + repeated VotePoll votes = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + +// QueryVotesForPollByVoterRequest is the Query/VotePollsByVoter request type. +message QueryVotesForPollByVoterRequest { + // voter is a poll voter account address. + string voter = 1; + + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 2; +} + +// QueryVotesForPollByVoterResponse is the Query/VotePollsByVoter response type. +message QueryVotesForPollByVoterResponse { + + // votes are the list of votes for poll by given voter. + repeated VotePoll votes = 1; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} \ No newline at end of file diff --git a/proto/regen/group/v1alpha1/tx.proto b/proto/regen/group/v1alpha1/tx.proto new file mode 100644 index 0000000000..1fa82fc651 --- /dev/null +++ b/proto/regen/group/v1alpha1/tx.proto @@ -0,0 +1,480 @@ +syntax = "proto3"; + +package regen.group.v1alpha1; + +option go_package = "github.com/cosmos/cosmos-sdk/x/group"; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +//import "cosmos.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; +import "regen/group/v1alpha1/types.proto"; + +// Msg is the regen.group.v1alpha1 Msg service. +service Msg { + + // CreateGroup creates a new group with an admin account address, a list of members and some optional metadata. + rpc CreateGroup(MsgCreateGroup) returns (MsgCreateGroupResponse); + + // UpdateGroupMembers updates the group members with given group id and admin address. + rpc UpdateGroupMembers(MsgUpdateGroupMembers) returns (MsgUpdateGroupMembersResponse); + + // UpdateGroupAdmin updates the group admin with given group id and previous admin address. + rpc UpdateGroupAdmin(MsgUpdateGroupAdmin) returns (MsgUpdateGroupAdminResponse); + + // UpdateGroupMetadata updates the group metadata with given group id and admin address. + rpc UpdateGroupMetadata(MsgUpdateGroupMetadata) returns (MsgUpdateGroupMetadataResponse); + + // CreateGroupAccount creates a new group account using given DecisionPolicy. + rpc CreateGroupAccount(MsgCreateGroupAccount) returns (MsgCreateGroupAccountResponse); + + // UpdateGroupAccountAdmin updates a group account admin. + rpc UpdateGroupAccountAdmin(MsgUpdateGroupAccountAdmin) returns (MsgUpdateGroupAccountAdminResponse); + + // UpdateGroupAccountDecisionPolicy allows a group account decision policy to be updated. + rpc UpdateGroupAccountDecisionPolicy(MsgUpdateGroupAccountDecisionPolicy) returns (MsgUpdateGroupAccountDecisionPolicyResponse); + + // UpdateGroupAccountMetadata updates a group account metadata. + rpc UpdateGroupAccountMetadata(MsgUpdateGroupAccountMetadata) returns (MsgUpdateGroupAccountMetadataResponse); + + // CreateProposal submits a new proposal. + rpc CreateProposal(MsgCreateProposal) returns (MsgCreateProposalResponse); + + // Vote allows a voter to vote on a proposal. + rpc Vote(MsgVote) returns (MsgVoteResponse); + + // VoteAgg allows a sender to submit a set of votes + rpc VoteAgg(MsgVoteAgg) returns (MsgVoteAggResponse); + + // Exec executes a proposal. + rpc Exec(MsgExec) returns (MsgExecResponse); + + // CreatePoll submits a new poll. + rpc CreatePoll(MsgCreatePoll) returns (MsgCreatePollResponse); + + // VotePoll allows a voter to vote on a poll. + rpc VotePoll(MsgVotePoll) returns (MsgVotePollResponse); + + // VotePollAgg allows a sender to submit a set of votes + rpc VotePollAgg(MsgVotePollAgg) returns (MsgVotePollAggResponse); +} + +// +// Groups +// + +// MsgCreateGroup is the Msg/CreateGroup request type. +message MsgCreateGroup { + + // admin is the account address of the group admin. + string admin = 1; + + // members defines the group members. + repeated Member members = 2 [(gogoproto.nullable) = false]; + + // metadata is any arbitrary metadata to attached to the group. + bytes metadata = 3; + + // bls_only requires all the group members to use bls public keys so their votes can be aggregated together + bool bls_only = 4; +} + +// MsgCreateGroupResponse is the Msg/CreateGroup response type. +message MsgCreateGroupResponse { + + // group_id is the unique ID of the newly created group. + uint64 group_id = 1; +} + +// MsgUpdateGroupMembers is the Msg/UpdateGroupMembers request type. +message MsgUpdateGroupMembers { + + // admin is the account address of the group admin. + string admin = 1; + + // group_id is the unique ID of the group. + uint64 group_id = 2; + + // member_updates is the list of members to update, + // set weight to 0 to remove a member. + repeated Member member_updates = 3 [(gogoproto.nullable) = false]; +} + +// MsgUpdateGroupMembersResponse is the Msg/UpdateGroupMembers response type. +message MsgUpdateGroupMembersResponse { } + +// MsgUpdateGroupAdmin is the Msg/UpdateGroupAdmin request type. +message MsgUpdateGroupAdmin { + + // admin is the current account address of the group admin. + string admin = 1; + + // group_id is the unique ID of the group. + uint64 group_id = 2; + + // new_admin is the group new admin account address. + string new_admin = 3; +} + +// MsgUpdateGroupAdminResponse is the Msg/UpdateGroupAdmin response type. +message MsgUpdateGroupAdminResponse { } + +// MsgUpdateGroupMetadata is the Msg/UpdateGroupMetadata request type. +message MsgUpdateGroupMetadata { + + // admin is the account address of the group admin. + string admin = 1; + + // group_id is the unique ID of the group. + uint64 group_id = 2; + + // metadata is the updated group's metadata. + bytes metadata = 3; +} + +// MsgUpdateGroupMetadataResponse is the Msg/UpdateGroupMetadata response type. +message MsgUpdateGroupMetadataResponse { } + +// +// Group Accounts +// + +// MsgCreateGroupAccount is the Msg/CreateGroupAccount request type. +message MsgCreateGroupAccount { + option (gogoproto.goproto_getters) = false; + + // admin is the account address of the group admin. + string admin = 1; + + // group_id is the unique ID of the group. + uint64 group_id = 2; + + // metadata is any arbitrary metadata to attached to the group account. + bytes metadata = 3; + + // decision_policy specifies the group account's decision policy. + google.protobuf.Any decision_policy = 4 [(cosmos_proto.accepts_interface) = "DecisionPolicy"]; +} + +// MsgCreateGroupAccountResponse is the Msg/CreateGroupAccount response type. +message MsgCreateGroupAccountResponse { + + // address is the account address of the newly created group account. + string address = 1; +} + +// MsgUpdateGroupAccountAdmin is the Msg/UpdateGroupAccountAdmin request type. +message MsgUpdateGroupAccountAdmin { + + // admin is the account address of the group admin. + string admin = 1; + + // address is the group account address. + string address = 2; + + // new_admin is the new group account admin. + string new_admin = 3; +} + +// MsgUpdateGroupAccountAdminResponse is the Msg/UpdateGroupAccountAdmin response type. +message MsgUpdateGroupAccountAdminResponse { } + +// MsgUpdateGroupAccountDecisionPolicy is the Msg/UpdateGroupAccountDecisionPolicy request type. +message MsgUpdateGroupAccountDecisionPolicy { + option (gogoproto.goproto_getters) = false; + + // admin is the account address of the group admin. + string admin = 1; + + // address is the group account address. + string address = 2; + + // decision_policy is the updated group account decision policy. + google.protobuf.Any decision_policy = 3 [(cosmos_proto.accepts_interface) = "DecisionPolicy"]; +} + +// MsgUpdateGroupAccountDecisionPolicyResponse is the Msg/UpdateGroupAccountDecisionPolicy response type. +message MsgUpdateGroupAccountDecisionPolicyResponse { } + +// MsgUpdateGroupAccountMetadata is the Msg/UpdateGroupAccountMetadata request type. +message MsgUpdateGroupAccountMetadata { + + // admin is the account address of the group admin. + string admin = 1; + + // address is the group account address. + string address = 2; + + // metadata is the updated group account metadata. + bytes metadata = 3; +} + +// MsgUpdateGroupAccountMetadataResponse is the Msg/UpdateGroupAccountMetadata response type. +message MsgUpdateGroupAccountMetadataResponse { } + +// +// Proposals and Voting +// + +// Exec defines modes of execution of a proposal on creation or on new vote. +enum Exec { + + // An empty value means that there should be a separate + // MsgExec request for the proposal to execute. + EXEC_UNSPECIFIED = 0; + + // Try to execute the proposal immediately. + // If the proposal is not allowed per the DecisionPolicy, + // the proposal will still be open and could + // be executed at a later point. + EXEC_TRY = 1; +} + +// MsgCreateProposal is the Msg/CreateProposal request type. +message MsgCreateProposal { + option (gogoproto.goproto_getters) = false; + + // address is the group account address. + string address = 1; + + // proposers are the account addresses of the proposers. + // Proposers signatures will be counted as yes votes. + repeated string proposers = 2; + + // metadata is any arbitrary metadata to attached to the proposal. + bytes metadata = 3; + + // msgs is a list of Msgs that will be executed if the proposal passes. + repeated google.protobuf.Any msgs = 4; + + // exec defines the mode of execution of the proposal, + // whether it should be executed immediately on creation or not. + // If so, proposers signatures are considered as Yes votes. + Exec exec = 5; +} + +// MsgCreateProposalResponse is the Msg/CreateProposal response type. +message MsgCreateProposalResponse { + + // proposal is the unique ID of the proposal. + uint64 proposal_id = 1; +} + +// MsgVote is the Msg/Vote request type. +message MsgVote { + + // proposal is the unique ID of the proposal. + uint64 proposal_id = 1; + + // voter is the voter account address. + string voter = 2; + + // choice is the voter's choice on the proposal. + Choice choice = 3; + + // metadata is any arbitrary metadata to attached to the vote. + bytes metadata = 4; + + // exec defines whether the proposal should be executed + // immediately after voting or not. + Exec exec = 5; +} + +// MsgVoteResponse is the Msg/Vote response type. +message MsgVoteResponse { } + + +// MsgVoteBasicRequest is the Msg/Vote request type. +message MsgVoteBasic { + + // proposal is the unique ID of the proposal. + uint64 proposal_id = 1; + + // choice is the voter's choice on the proposal. + Choice choice = 2; + + // expiry is the timestamp after which the basic vote expires. + google.protobuf.Timestamp expiry = 3 [(gogoproto.nullable) = false]; +} + +// MsgVoteResponse is the basic vote that can be aggregated together +message MsgVoteBasicResponse { + // proposal is the unique ID of the proposal. + uint64 proposal_id = 1; + + // choice is the voter's choice on the proposal. + Choice choice = 2; + + // expiry is the timestamp after which the basic vote expires. + google.protobuf.Timestamp expiry = 3 [(gogoproto.nullable) = false]; + + // voter is the account address of the voter. + string voter = 4; + + // pub_key is the voter's public key + google.protobuf.Any pub_key = 5 + [(gogoproto.jsontag) = "public_key,omitempty", (gogoproto.moretags) = "yaml:\"public_key\""]; + + // sig is the individual signature which will be aggregated with other signatures + bytes sig = 6; +} + +// MsgVoteAgg is the Msg/VoteAgg request type. +message MsgVoteAgg { + // sender is the person who submits the votes + string sender = 1; + + // proposal is the unique ID of the proposal. + uint64 proposal_id = 2; + + // votes are the list of voters' choices on the proposal. + repeated Choice votes = 3; + + // expiry is the timestamp after which the basic vote expires. + // All the basic votes to be aggregated must have the same expiry. + // Expiry should be set to be before the proposal timeout in order to + // prevent replay attacks and also prevent the aggregator from removing + // some basic votes. + google.protobuf.Timestamp expiry = 4 [(gogoproto.nullable) = false]; + + // agg_sig is the bls aggregated signature for all the votes + bytes agg_sig = 5; + + // metadata is any arbitrary metadata attached to the vote. + bytes metadata = 6; + + // exec defines whether the proposal should be executed + // immediately after voting or not. + Exec exec = 7; +} + +// MsgVoteResponse is the Msg/Vote response type. +message MsgVoteAggResponse { } + +// MsgExec is the Msg/Exec request type. +message MsgExec { + + // proposal is the unique ID of the proposal. + uint64 proposal_id = 1; + + // signer is the account address used to execute the proposal. + string signer = 2; +} + +// MsgExecResponse is the Msg/Exec request type. +message MsgExecResponse { } + + + +// MsgCreateProposal is the Msg/CreateProposal request type. +message MsgCreatePoll { + option (gogoproto.goproto_getters) = false; + + // group_id is the unique ID of the group. + uint64 group_id = 1; + + string title = 2; + + Options options = 3 [(gogoproto.nullable) = false];; + + string creator = 4; + + // vote_limit is the number of options each voter can choose. + int32 vote_limit = 5; + + // metadata is any arbitrary metadata to attached to the proposal. + bytes metadata = 6; + + // timeout is the deadline of the poll. + google.protobuf.Timestamp timeout = 7 [(gogoproto.nullable) = false]; +} + +// MsgCreateProposalResponse is the Msg/CreateProposal response type. +message MsgCreatePollResponse { + + // poll_id is the unique ID of the poll. + uint64 poll_id = 1; +} + +// MsgVotePoll is the Msg/VotePoll request type. +message MsgVotePoll { + + // poll_id is the unique ID of the poll. + uint64 poll_id = 1; + + // voter is the voter account address. + string voter = 2; + + // options are the voter's choices on the poll. + Options options = 3 [(gogoproto.nullable) = false]; + + // metadata is any arbitrary metadata to attached to the vote. + bytes metadata = 4; +} + +// MsgVotePollResponse is the Msg/VotePoll response type. +message MsgVotePollResponse { } + +// MsgVoteBasicRequest is the Msg/Vote request type. +message MsgVotePollBasic { + + // poll_id is the unique ID of the poll. + uint64 poll_id = 1; + + // option is one of the voter's choices on the poll. + string option = 2; + + // expiry is the unique timestamp after which the basic vote expires. + google.protobuf.Timestamp expiry = 3 [(gogoproto.nullable) = false]; +} + +// MsgVoteResponse is the basic vote that can be aggregated together +message MsgVotePollBasicResponse { + // proposal is the unique ID of the proposal. + uint64 poll_id = 1; + + // options are the voter's choices on the poll. + Options options = 2 [(gogoproto.nullable) = false]; + + // expiry is the timestamp after which the basic vote expires. + google.protobuf.Timestamp expiry = 3 [(gogoproto.nullable) = false]; + + // voter is the account address of the voter. + string voter = 4; + + // pub_key is the voter's public key + google.protobuf.Any pub_key = 5 + [(gogoproto.jsontag) = "public_key,omitempty", (gogoproto.moretags) = "yaml:\"public_key\""]; + + // sig is the individual signature which will be aggregated with other voters' signatures + bytes sig = 6; +} + +// MsgVoteAgg is the Msg/VoteAgg request type. +message MsgVotePollAgg { + // sender is the person who submits the votes + string sender = 1; + + // poll_id is the unique ID of the poll. + uint64 poll_id = 2; + + // votes are the full list of voters' choices on the proposal. + repeated Options votes = 3 [(gogoproto.nullable) = false]; + + // expiry is the timestamp after which the basic vote expires. + // All the basic votes to be aggregated must have the same expiry. + // Expiry should be set to be before the poll timeout in order to + // prevent replay attacks and also prevent the aggregator from removing + // some basic votes. + google.protobuf.Timestamp expiry = 4 [(gogoproto.nullable) = false]; + + // agg_sig is the bls aggregated signature for all the votes + bytes agg_sig = 5; + + // metadata is any arbitrary metadata to attached to the vote. + bytes metadata = 6; +} + +// MsgVoteResponse is the Msg/Vote response type. +message MsgVotePollAggResponse { } \ No newline at end of file diff --git a/proto/regen/group/v1alpha1/types.proto b/proto/regen/group/v1alpha1/types.proto new file mode 100644 index 0000000000..640c48c774 --- /dev/null +++ b/proto/regen/group/v1alpha1/types.proto @@ -0,0 +1,372 @@ +syntax = "proto3"; + +package regen.group.v1alpha1; + +option go_package = "github.com/cosmos/cosmos-sdk/x/group"; + +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "cosmos_proto/cosmos.proto"; +//import "cosmos.proto"; +import "google/protobuf/any.proto"; + +// Member represents a group member with an account address, +// non-zero weight and metadata. +message Member { + + // address is the member's account address. + string address = 1; + + // weight is the member's voting weight that should be greater than 0. + string weight = 2; + + // metadata is any arbitrary metadata to attached to the member. + bytes metadata = 3; +} + +// Members defines a repeated slice of Member objects. +message Members { + + // members is the list of members. + repeated Member members = 1 [(gogoproto.nullable) = false]; +} + +// ThresholdDecisionPolicy implements the DecisionPolicy interface +message ThresholdDecisionPolicy { + option (cosmos_proto.implements_interface) = "DecisionPolicy"; + + // threshold is the minimum weighted sum of yes votes that must be met or exceeded for a proposal to succeed. + string threshold = 1; + + // timeout is the duration from submission of a proposal to the end of voting period + // Within this times votes and exec messages can be submitted. + google.protobuf.Duration timeout = 2 [(gogoproto.nullable) = false]; +} + +// Choice defines available types of choices for voting. +enum Choice { + + // CHOICE_UNSPECIFIED defines a no-op voting choice. + CHOICE_UNSPECIFIED = 0; + + // CHOICE_NO defines a no voting choice. + CHOICE_NO = 1; + + // CHOICE_YES defines a yes voting choice. + CHOICE_YES = 2; + + // CHOICE_ABSTAIN defines an abstaining voting choice. + CHOICE_ABSTAIN = 3; + + // CHOICE_VETO defines a voting choice with veto. + CHOICE_VETO = 4; +} + +// +// State +// + +// GroupInfo represents the high-level on-chain information for a group. +message GroupInfo { + + // group_id is the unique ID of the group. + uint64 group_id = 1; + + // admin is the account address of the group's admin. + string admin = 2; + + // metadata is any arbitrary metadata to attached to the group. + bytes metadata = 3; + + // version is used to track changes to a group's membership structure that + // would break existing proposals. Whenever any members weight is changed, + // or any member is added or removed this version is incremented and will + // cause proposals based on older versions of this group to fail + uint64 version = 4; + + // total_weight is the sum of the group members' weights. + string total_weight = 5; + + // bls_only requires all the group members to use bls public keys so their votes can be aggregated together + bool bls_only = 6; +} + +// GroupMember represents the relationship between a group and a member. +message GroupMember { + + // group_id is the unique ID of the group. + uint64 group_id = 1; + + // member is the member data. + Member member = 2; +} + +// GroupAccountInfo represents the high-level on-chain information for a group account. +message GroupAccountInfo { + option (gogoproto.equal) = true; + option (gogoproto.goproto_getters) = false; + + // address is the group account address. + string address = 1; + + // group_id is the unique ID of the group. + uint64 group_id = 2; + + // admin is the account address of the group admin. + string admin = 3; + + // metadata is any arbitrary metadata to attached to the group account. + bytes metadata = 4; + + // version is used to track changes to a group's GroupAccountInfo structure that + // would create a different result on a running proposal. + uint64 version = 5; + + // decision_policy specifies the group account's decision policy. + google.protobuf.Any decision_policy = 6 [(cosmos_proto.accepts_interface) = "DecisionPolicy"]; + + // derivation_key is the "derivation" key of the group account, + // which is needed to derive the group root module key and execute proposals. + bytes derivation_key = 7; + +} + +// Proposal defines a group proposal. Any member of a group can submit a proposal +// for a group account to decide upon. +// A proposal consists of a set of `sdk.Msg`s that will be executed if the proposal +// passes as well as some optional metadata associated with the proposal. +message Proposal { + option (gogoproto.goproto_getters) = false; + + // proposal_id is the unique id of the proposal. + uint64 proposal_id = 1; + + // address is the group account address. + string address = 2; + + // metadata is any arbitrary metadata to attached to the proposal. + bytes metadata = 3; + + // proposers are the account addresses of the proposers. + repeated string proposers = 4; + + // submitted_at is a timestamp specifying when a proposal was submitted. + google.protobuf.Timestamp submitted_at = 5 [(gogoproto.nullable) = false]; + + // group_version tracks the version of the group that this proposal corresponds to. + // When group membership is changed, existing proposals from previous group versions will become invalid. + uint64 group_version = 6; + + // group_account_version tracks the version of the group account that this proposal corresponds to. + // When a decision policy is changed, existing proposals from previous policy versions will become invalid. + uint64 group_account_version = 7; + + // Status defines proposal statuses. + enum Status { + option (gogoproto.goproto_enum_prefix) = false; + + // An empty value is invalid and not allowed. + STATUS_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ProposalStatusInvalid"]; + + // Initial status of a proposal when persisted. + STATUS_SUBMITTED = 1 [(gogoproto.enumvalue_customname) = "ProposalStatusSubmitted"]; + + // Final status of a proposal when the final tally was executed. + STATUS_CLOSED = 2 [(gogoproto.enumvalue_customname) = "ProposalStatusClosed"]; + + // Final status of a proposal when the group was modified before the final tally. + STATUS_ABORTED = 3 [(gogoproto.enumvalue_customname) = "ProposalStatusAborted"]; + + // TODO: do we want to support a withdrawn operation? + // A proposal can be deleted before the voting start time by the owner. When this happens the final status + // is Withdrawn. + // STATUS_WITHDRAWN = 4 [(gogoproto.enumvalue_customname) = "Withdrawn"]; + } + + // Status represents the high level position in the life cycle of the proposal. Initial value is Submitted. + Status status = 8; + + // Result defines types of proposal results. + enum Result { + option (gogoproto.goproto_enum_prefix) = false; + + // An empty value is invalid and not allowed + RESULT_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ProposalResultInvalid"]; + + // Until a final tally has happened the status is unfinalized + RESULT_UNFINALIZED = 1 [(gogoproto.enumvalue_customname) = "ProposalResultUnfinalized"]; + + // Final result of the tally + RESULT_ACCEPTED = 2 [(gogoproto.enumvalue_customname) = "ProposalResultAccepted"]; + + // Final result of the tally + RESULT_REJECTED = 3 [(gogoproto.enumvalue_customname) = "ProposalResultRejected"]; + } + + // result is the final result based on the votes and election rule. Initial value is unfinalized. + // The result is persisted so that clients can always rely on this state and not have to replicate the logic. + Result result = 9; + + // vote_state contains the sums of all weighted votes for this proposal. + Tally vote_state = 10 [(gogoproto.nullable) = false]; + + // timeout is the timestamp of the block where the proposal execution times out. Header times of the votes and execution messages + // must be before this end time to be included in the election. After the timeout timestamp the proposal can not be + // executed anymore and should be considered pending delete. + google.protobuf.Timestamp timeout = 11 [(gogoproto.nullable) = false]; + + // ExecutorResult defines types of proposal executor results. + enum ExecutorResult { + option (gogoproto.goproto_enum_prefix) = false; + + // An empty value is not allowed. + EXECUTOR_RESULT_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultInvalid"]; + + // We have not yet run the executor. + EXECUTOR_RESULT_NOT_RUN = 1 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultNotRun"]; + + // The executor was successful and proposed action updated state. + EXECUTOR_RESULT_SUCCESS = 2 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultSuccess"]; + + // The executor returned an error and proposed action didn't update state. + EXECUTOR_RESULT_FAILURE = 3 [(gogoproto.enumvalue_customname) = "ProposalExecutorResultFailure"]; + } + + // executor_result is the final result based on the votes and election rule. Initial value is NotRun. + ExecutorResult executor_result = 12; + + // msgs is a list of Msgs that will be executed if the proposal passes. + repeated google.protobuf.Any msgs = 13; +} + +// Tally represents the sum of weighted votes. +message Tally { + option (gogoproto.goproto_getters) = false; + + // yes_count is the weighted sum of yes votes. + string yes_count = 1; + + // no_count is the weighted sum of no votes. + string no_count = 2; + + // abstain_count is the weighted sum of abstainers + string abstain_count = 3; + + // veto_count is the weighted sum of vetoes. + string veto_count = 4; +} + +// Vote represents a vote for a proposal. +message Vote { + + // proposal is the unique ID of the proposal. + uint64 proposal_id = 1; + + // voter is the account address of the voter. + string voter = 2; + + // choice is the voter's choice on the proposal. + Choice choice = 3; + + // metadata is any arbitrary metadata to attached to the vote. + bytes metadata = 4; + + // submitted_at is the timestamp when the vote was submitted. + google.protobuf.Timestamp submitted_at = 5 [(gogoproto.nullable) = false]; +} + +// TallyPoll represents the sum of weighted votes for a poll. +message TallyPoll { + option (gogoproto.goproto_getters) = false; + map counts = 1; +} + +// Options represents the choices voters can vote for a poll. +message Options { + option (gogoproto.goproto_getters) = false; + + repeated string titles = 1; +} + +// Poll defines a group poll. Any member of a group can submit a poll +// for a group to decide upon. +// The options in a poll can be customised by the creator. +message Poll { + option (gogoproto.goproto_getters) = false; + + // poll_id is the unique id of the poll. + uint64 poll_id = 1; + + // group_id is the unique ID of the group. + uint64 group_id = 2; + + // title is the title of the poll. + string title = 3; + + // options are the choices of the poll. + Options options = 4 [(gogoproto.nullable) = false]; + + // creator is the account address of the poll creator. + string creator = 5; + + // vote_limit is the maximum number of options each voter can choose. + int32 vote_limit = 6; + + // vote_state contains the sums of all weighted votes for this poll. + TallyPoll vote_state = 7 [(gogoproto.nullable) = false]; + + // metadata is any arbitrary metadata to attached to the poll. + bytes metadata = 8; + + // submitted_at is a timestamp specifying when a poll was submitted. + google.protobuf.Timestamp submitted_at = 9 [(gogoproto.nullable) = false]; + + // group_version tracks the version of the group that this poll corresponds to. + // When group membership is changed, existing polls from previous group versions will become invalid. + uint64 group_version = 10; + + // Status defines poll statuses. + enum Status { + option (gogoproto.goproto_enum_prefix) = false; + + // An empty value is invalid and not allowed. + STATUS_UNSPECIFIED = 0 [(gogoproto.enumvalue_customname) = "PollStatusInvalid"]; + + // Initial status of a poll when persisted. + STATUS_SUBMITTED = 1 [(gogoproto.enumvalue_customname) = "PollStatusSubmitted"]; + + // Final status of a poll when the final tally was executed. + STATUS_CLOSED = 2 [(gogoproto.enumvalue_customname) = "PollStatusClosed"]; + + // Final status of a poll when the group was modified before the final tally. + STATUS_ABORTED = 3 [(gogoproto.enumvalue_customname) = "PollStatusAborted"]; + } + + // Status represents the high level position in the life cycle of the poll. Initial value is Submitted. + Status status = 11; + + // timeout is the timestamp of the block where the poll times out. Header times of the votes + // must be before this end time to be included in the election. + google.protobuf.Timestamp timeout = 12 [(gogoproto.nullable) = false]; +} + + +// VotePoll represents a vote for a poll. +message VotePoll { + + // poll_id is the unique ID of the pool. + uint64 poll_id = 1; + + // voter is the account address of the voter. + string voter = 2; + + // options are the voter's choices on the poll. + Options options = 3 [(gogoproto.nullable) = false];; + + // metadata is any arbitrary metadata to attached to the vote. + bytes metadata = 4; + + // submitted_at is the timestamp when the vote was submitted. + google.protobuf.Timestamp submitted_at = 5 [(gogoproto.nullable) = false]; +} \ No newline at end of file diff --git a/regen/orm/auto_uint64.go b/regen/orm/auto_uint64.go new file mode 100644 index 0000000000..90bbcbbc70 --- /dev/null +++ b/regen/orm/auto_uint64.go @@ -0,0 +1,130 @@ +package orm + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ Indexable = &AutoUInt64TableBuilder{} + +// NewAutoUInt64TableBuilder creates a builder to setup a AutoUInt64Table object. +func NewAutoUInt64TableBuilder(prefixData byte, prefixSeq byte, storeKey sdk.StoreKey, model codec.ProtoMarshaler, cdc codec.Codec) *AutoUInt64TableBuilder { + if prefixData == prefixSeq { + panic("prefixData and prefixSeq must be unique") + } + + uInt64KeyCodec := FixLengthIndexKeys(EncodedSeqLength) + return &AutoUInt64TableBuilder{ + tableBuilder: newTableBuilder(prefixData, storeKey, model, uInt64KeyCodec, cdc), + seq: NewSequence(storeKey, prefixSeq), + } +} + +type AutoUInt64TableBuilder struct { + *tableBuilder + seq Sequence +} + +// Build create the AutoUInt64Table object. +func (a AutoUInt64TableBuilder) Build() AutoUInt64Table { + return AutoUInt64Table{ + table: a.tableBuilder.Build(), + seq: a.seq, + } +} + +var _ SequenceExportable = &AutoUInt64Table{} +var _ TableExportable = &AutoUInt64Table{} + +// AutoUInt64Table is the table type which an auto incrementing ID. +type AutoUInt64Table struct { + table table + seq Sequence +} + +// Create a new persistent object with an auto generated uint64 primary key. They key is returned. +// Create iterates though the registered callbacks and may add secondary index keys by them. +func (a AutoUInt64Table) Create(ctx HasKVStore, obj codec.ProtoMarshaler) (uint64, error) { + autoIncID := a.seq.NextVal(ctx) + err := a.table.Create(ctx, EncodeSequence(autoIncID), obj) + if err != nil { + return 0, err + } + return autoIncID, nil +} + +// Save updates the given object under the rowID key. It expects the key to exists already +// and fails with an `ErrNotFound` otherwise. Any caller must therefore make sure that this contract +// is fulfilled. Parameters must not be nil. +// +// Save iterates though the registered callbacks and may add or remove secondary index keys by them. +func (a AutoUInt64Table) Save(ctx HasKVStore, rowID uint64, newValue codec.ProtoMarshaler) error { + return a.table.Save(ctx, EncodeSequence(rowID), newValue) +} + +// Delete removes the object under the rowID key. It expects the key to exists already +// and fails with a `ErrNotFound` otherwise. Any caller must therefore make sure that this contract +// is fulfilled. +// +// Delete iterates though the registered callbacks and removes secondary index keys by them. +func (a AutoUInt64Table) Delete(ctx HasKVStore, rowID uint64) error { + return a.table.Delete(ctx, EncodeSequence(rowID)) +} + +// Has checks if a rowID exists. +func (a AutoUInt64Table) Has(ctx HasKVStore, rowID uint64) bool { + return a.table.Has(ctx, EncodeSequence(rowID)) +} + +// GetOne load the object persisted for the given RowID into the dest parameter. +// If none exists `ErrNotFound` is returned instead. Parameters must not be nil. +func (a AutoUInt64Table) GetOne(ctx HasKVStore, rowID uint64, dest codec.ProtoMarshaler) (RowID, error) { + rawRowID := EncodeSequence(rowID) + if err := a.table.GetOne(ctx, rawRowID, dest); err != nil { + return nil, err + } + return rawRowID, nil +} + +// PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. +// Example: +// it, err := idx.PrefixScan(ctx, start, end) +// if err !=nil { +// return err +// } +// const defaultLimit = 20 +// it = LimitIterator(it, defaultLimit) +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (a AutoUInt64Table) PrefixScan(ctx HasKVStore, start, end uint64) (Iterator, error) { + return a.table.PrefixScan(ctx, EncodeSequence(start), EncodeSequence(end)) +} + +// ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. See `LimitIterator` +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (a AutoUInt64Table) ReversePrefixScan(ctx HasKVStore, start uint64, end uint64) (Iterator, error) { + return a.table.ReversePrefixScan(ctx, EncodeSequence(start), EncodeSequence(end)) +} + +// Sequence returns the sequence used by this table +func (a AutoUInt64Table) Sequence() Sequence { + return a.seq +} + +// Table satisfies the TableExportable interface and must not be used otherwise. +func (a AutoUInt64Table) Table() table { + return a.table +} diff --git a/regen/orm/auto_uint64_test.go b/regen/orm/auto_uint64_test.go new file mode 100644 index 0000000000..b6aebeeb31 --- /dev/null +++ b/regen/orm/auto_uint64_test.go @@ -0,0 +1,163 @@ +package orm_test + +import ( + "math" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestAutoUInt64PrefixScan(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const ( + testTablePrefix = iota + testTableSeqPrefix + ) + tb := orm.NewAutoUInt64TableBuilder(testTablePrefix, testTableSeqPrefix, storeKey, &testdata.GroupInfo{}, cdc).Build() + ctx := orm.NewMockContext() + + g1 := testdata.GroupInfo{ + Description: "my test 1", + Admin: sdk.AccAddress([]byte("admin-address")), + } + g2 := testdata.GroupInfo{ + Description: "my test 2", + Admin: sdk.AccAddress([]byte("admin-address")), + } + g3 := testdata.GroupInfo{ + Description: "my test 3", + Admin: sdk.AccAddress([]byte("admin-address")), + } + for _, g := range []testdata.GroupInfo{g1, g2, g3} { + _, err := tb.Create(ctx, &g) + require.NoError(t, err) + } + + specs := map[string]struct { + start, end uint64 + expResult []testdata.GroupInfo + expRowIDs []orm.RowID + expError *errors.Error + method func(ctx orm.HasKVStore, start uint64, end uint64) (orm.Iterator, error) + }{ + "first element": { + start: 1, + end: 2, + method: tb.PrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "first 2 elements": { + start: 1, + end: 3, + method: tb.PrefixScan, + expResult: []testdata.GroupInfo{g1, g2}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1), orm.EncodeSequence(2)}, + }, + "first 3 elements": { + start: 1, + end: 4, + method: tb.PrefixScan, + expResult: []testdata.GroupInfo{g1, g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1), orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "search with max end": { + start: 1, + end: math.MaxUint64, + method: tb.PrefixScan, + expResult: []testdata.GroupInfo{g1, g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1), orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "2 to end": { + start: 2, + end: 5, + method: tb.PrefixScan, + expResult: []testdata.GroupInfo{g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "start before end should fail": { + start: 2, + end: 1, + method: tb.PrefixScan, + expError: orm.ErrArgument, + }, + "start equals end should fail": { + start: 1, + end: 1, + method: tb.PrefixScan, + expError: orm.ErrArgument, + }, + "reverse first element": { + start: 1, + end: 2, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "reverse first 2 elements": { + start: 1, + end: 3, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupInfo{g2, g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(2), orm.EncodeSequence(1)}, + }, + "reverse first 3 elements": { + start: 1, + end: 4, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2, g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2), orm.EncodeSequence(1)}, + }, + "reverse search with max end": { + start: 1, + end: math.MaxUint64, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2, g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2), orm.EncodeSequence(1)}, + }, + "reverse 2 to end": { + start: 2, + end: 5, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2)}, + }, + "reverse start before end should fail": { + start: 2, + end: 1, + method: tb.ReversePrefixScan, + expError: orm.ErrArgument, + }, + "reverse start equals end should fail": { + start: 1, + end: 1, + method: tb.ReversePrefixScan, + expError: orm.ErrArgument, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + it, err := spec.method(ctx, spec.start, spec.end) + require.True(t, spec.expError.Is(err), "expected #+v but got #+v", spec.expError, err) + if spec.expError != nil { + return + } + var loaded []testdata.GroupInfo + rowIDs, err := orm.ReadAll(it, &loaded) + require.NoError(t, err) + assert.Equal(t, spec.expResult, loaded) + assert.Equal(t, spec.expRowIDs, rowIDs) + }) + } +} diff --git a/regen/orm/example_test.go b/regen/orm/example_test.go new file mode 100644 index 0000000000..3ff536f700 --- /dev/null +++ b/regen/orm/example_test.go @@ -0,0 +1,53 @@ +package orm_test + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +type GroupKeeper struct { + key sdk.StoreKey + groupTable orm.AutoUInt64Table + groupByAdminIndex orm.Index + groupMemberTable orm.PrimaryKeyTable + groupMemberByGroupIndex orm.Index + groupMemberByMemberIndex orm.Index +} + +var ( + GroupTablePrefix byte = 0x0 + GroupTableSeqPrefix byte = 0x1 + GroupByAdminIndexPrefix byte = 0x2 + GroupMemberTablePrefix byte = 0x3 + GroupMemberTableSeqPrefix byte = 0x4 + GroupMemberTableIndexPrefix byte = 0x5 + GroupMemberByGroupIndexPrefix byte = 0x6 + GroupMemberByMemberIndexPrefix byte = 0x7 +) + +func NewGroupKeeper(storeKey sdk.StoreKey, cdc codec.Codec) GroupKeeper { + k := GroupKeeper{key: storeKey} + + groupTableBuilder := orm.NewAutoUInt64TableBuilder(GroupTablePrefix, GroupTableSeqPrefix, storeKey, &testdata.GroupInfo{}, cdc) + // note: quite easy to mess with Index prefixes when managed outside. no fail fast on duplicates + k.groupByAdminIndex = orm.NewIndex(groupTableBuilder, GroupByAdminIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + return []orm.RowID{[]byte(val.(*testdata.GroupInfo).Admin)}, nil + }) + k.groupTable = groupTableBuilder.Build() + + groupMemberTableBuilder := orm.NewPrimaryKeyTableBuilder(GroupMemberTablePrefix, storeKey, &testdata.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + + k.groupMemberByGroupIndex = orm.NewIndex(groupMemberTableBuilder, GroupMemberByGroupIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + group := val.(*testdata.GroupMember).Group + return []orm.RowID{[]byte(group)}, nil + }) + k.groupMemberByMemberIndex = orm.NewIndex(groupMemberTableBuilder, GroupMemberByMemberIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + return []orm.RowID{[]byte(val.(*testdata.GroupMember).Member)}, nil + }) + k.groupMemberTable = groupMemberTableBuilder.Build() + + return k +} diff --git a/regen/orm/genesis.go b/regen/orm/genesis.go new file mode 100644 index 0000000000..dc9afd49b8 --- /dev/null +++ b/regen/orm/genesis.go @@ -0,0 +1,88 @@ +package orm + +import ( + "reflect" + + "github.com/cosmos/cosmos-sdk/store/prefix" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// TableExportable +type TableExportable interface { + // Table returns the table to export + Table() table +} + +// SequenceExportable +type SequenceExportable interface { + // Sequence returns the sequence to export + Sequence() Sequence +} + +// ExportTableData iterates over the given table entries and stores them at the passed ModelSlicePtr. +// When the given table implements the `SequenceExportable` interface then it's current value +// is returned as well or otherwise defaults to 0. +func ExportTableData(ctx HasKVStore, t TableExportable, dest ModelSlicePtr) (uint64, error) { + it, err := t.Table().PrefixScan(ctx, nil, nil) + if err != nil { + return 0, errors.Wrap(err, "table PrefixScan failure when exporting table data") + } + _, err = ReadAll(it, dest) + if err != nil { + return 0, err + } + var seqValue uint64 + if st, ok := t.(SequenceExportable); ok { + seqValue = st.Sequence().CurVal(ctx) + } + return seqValue, err +} + +// ImportTableData initializes a table and attaches indexers from the given data interface{}. +// data should be a slice of structs that implement PrimaryKeyed (eg []*GroupInfo). +// The seqValue is optional and only used with tables that implement the `SequenceExportable` interface. +func ImportTableData(ctx HasKVStore, t TableExportable, data interface{}, seqValue uint64) error { + table := t.Table() + if err := clearAllInTable(ctx, table); err != nil { + return errors.Wrap(err, "clear old entries") + } + + if st, ok := t.(SequenceExportable); ok { + if err := st.Sequence().InitVal(ctx, seqValue); err != nil { + return errors.Wrap(err, "sequence") + } + } + + // Provided data must be a slice + modelSlice := reflect.ValueOf(data) + if modelSlice.Kind() != reflect.Slice { + return errors.Wrap(ErrArgument, "data must be a slice") + } + + // Create table entries + for i := 0; i < modelSlice.Len(); i++ { + obj, ok := modelSlice.Index(i).Interface().(PrimaryKeyed) + if !ok { + return errors.Wrapf(ErrArgument, "unsupported type :%s", reflect.TypeOf(data).Elem().Elem()) + } + err := table.Create(ctx, PrimaryKey(obj), obj) + if err != nil { + return err + } + } + + return nil +} + +// clearAllInTable deletes all entries in a table with delete interceptors called +func clearAllInTable(ctx HasKVStore, table table) error { + store := prefix.NewStore(ctx.KVStore(table.storeKey), []byte{table.prefix}) + it := store.Iterator(nil, nil) + defer it.Close() + for ; it.Valid(); it.Next() { + if err := table.Delete(ctx, it.Key()); err != nil { + return err + } + } + return nil +} diff --git a/regen/orm/genesis_test.go b/regen/orm/genesis_test.go new file mode 100644 index 0000000000..8f06cccdec --- /dev/null +++ b/regen/orm/genesis_test.go @@ -0,0 +1,54 @@ +package orm_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" +) + +func TestImportExportTableData(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const prefix = iota + table := orm.NewAutoUInt64TableBuilder(prefix, 0x1, storeKey, &testdata.GroupInfo{}, cdc).Build() + + ctx := orm.NewMockContext() + + groups := []*testdata.GroupInfo{ + { + GroupId: 1, + Admin: sdk.AccAddress([]byte("admin1-address")), + }, + { + GroupId: 2, + Admin: sdk.AccAddress([]byte("admin2-address")), + }, + } + + err := orm.ImportTableData(ctx, table, groups, 2) + require.NoError(t, err) + + for _, g := range groups { + var loaded testdata.GroupInfo + _, err := table.GetOne(ctx, g.GroupId, &loaded) + require.NoError(t, err) + + require.Equal(t, g, &loaded) + } + + var exported []*testdata.GroupInfo + seq, err := orm.ExportTableData(ctx, table, &exported) + require.NoError(t, err) + require.Equal(t, seq, uint64(2)) + + for i, g := range exported { + require.Equal(t, g, groups[i]) + } +} diff --git a/regen/orm/index.go b/regen/orm/index.go new file mode 100644 index 0000000000..c918f446b1 --- /dev/null +++ b/regen/orm/index.go @@ -0,0 +1,219 @@ +package orm + +import ( + "bytes" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" +) + +// indexer creates and modifies the second MultiKeyIndex based on the operations and changes on the primary object. +type indexer interface { + OnCreate(store sdk.KVStore, rowID RowID, value interface{}) error + OnDelete(store sdk.KVStore, rowID RowID, value interface{}) error + OnUpdate(store sdk.KVStore, rowID RowID, newValue, oldValue interface{}) error +} + +// MultiKeyIndex is an index where multiple entries can point to the same underlying object as opposite to a unique index +// where only one entry is allowed. +type MultiKeyIndex struct { + storeKey sdk.StoreKey + prefix byte + rowGetter RowGetter + indexer indexer + indexKeyCodec IndexKeyCodec +} + +// NewIndex builds a MultiKeyIndex +func NewIndex(builder Indexable, prefix byte, indexer IndexerFunc) MultiKeyIndex { + return newIndex(builder, prefix, NewIndexer(indexer, builder.IndexKeyCodec())) +} + +func newIndex(builder Indexable, prefix byte, indexer *Indexer) MultiKeyIndex { + codec := builder.IndexKeyCodec() + if codec == nil { + panic("IndexKeyCodec must not be nil") + } + storeKey := builder.StoreKey() + if storeKey == nil { + panic("StoreKey must not be nil") + } + rowGetter := builder.RowGetter() + if rowGetter == nil { + panic("RowGetter must not be nil") + } + + idx := MultiKeyIndex{ + storeKey: storeKey, + prefix: prefix, + rowGetter: rowGetter, + indexer: indexer, + indexKeyCodec: codec, + } + builder.AddAfterSaveInterceptor(idx.onSave) + builder.AddAfterDeleteInterceptor(idx.onDelete) + return idx +} + +// Has checks if a key exists. Panics on nil key. +func (i MultiKeyIndex) Has(ctx HasKVStore, key []byte) bool { + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + it := store.Iterator(PrefixRange(key)) + defer it.Close() + return it.Valid() +} + +// Get returns a result iterator for the searchKey. Parameters must not be nil. +func (i MultiKeyIndex) Get(ctx HasKVStore, searchKey []byte) (Iterator, error) { + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + it := store.Iterator(PrefixRange(searchKey)) + return indexIterator{ctx: ctx, it: it, rowGetter: i.rowGetter, keyCodec: i.indexKeyCodec}, nil +} + +// GetPaginated creates an iterator for the searchKey +// starting from pageRequest.Key if provided. +// The pageRequest.Key is the rowID while searchKey is a MultiKeyIndex key. +func (i MultiKeyIndex) GetPaginated(ctx HasKVStore, searchKey []byte, pageRequest *query.PageRequest) (Iterator, error) { + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + start, end := PrefixRange(searchKey) + + if pageRequest != nil && len(pageRequest.Key) != 0 { + start = i.indexKeyCodec.BuildIndexKey(searchKey, RowID(pageRequest.Key)) + } + it := store.Iterator(start, end) + return indexIterator{ctx: ctx, it: it, rowGetter: i.rowGetter, keyCodec: i.indexKeyCodec}, nil +} + +// PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. +// Example: +// it, err := idx.PrefixScan(ctx, start, end) +// if err !=nil { +// return err +// } +// const defaultLimit = 20 +// it = LimitIterator(it, defaultLimit) +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (i MultiKeyIndex) PrefixScan(ctx HasKVStore, start []byte, end []byte) (Iterator, error) { + if start != nil && end != nil && bytes.Compare(start, end) >= 0 { + return NewInvalidIterator(), errors.Wrap(ErrArgument, "start must be less than end") + } + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + it := store.Iterator(start, end) + return indexIterator{ctx: ctx, it: it, rowGetter: i.rowGetter, keyCodec: i.indexKeyCodec}, nil +} + +// ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. See `LimitIterator` +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (i MultiKeyIndex) ReversePrefixScan(ctx HasKVStore, start []byte, end []byte) (Iterator, error) { + if start != nil && end != nil && bytes.Compare(start, end) >= 0 { + return NewInvalidIterator(), errors.Wrap(ErrArgument, "start must be less than end") + } + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + it := store.ReverseIterator(start, end) + return indexIterator{ctx: ctx, it: it, rowGetter: i.rowGetter, keyCodec: i.indexKeyCodec}, nil +} + +func (i MultiKeyIndex) onSave(ctx HasKVStore, rowID RowID, newValue, oldValue codec.ProtoMarshaler) error { + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + if oldValue == nil { + return i.indexer.OnCreate(store, rowID, newValue) + } + return i.indexer.OnUpdate(store, rowID, newValue, oldValue) +} + +func (i MultiKeyIndex) onDelete(ctx HasKVStore, rowID RowID, oldValue codec.ProtoMarshaler) error { + store := prefix.NewStore(ctx.KVStore(i.storeKey), []byte{i.prefix}) + return i.indexer.OnDelete(store, rowID, oldValue) +} + +type UniqueIndex struct { + MultiKeyIndex +} + +// NewUniqueIndex create a new Index object where duplicate keys are prohibited. +func NewUniqueIndex(builder Indexable, prefix byte, uniqueIndexerFunc UniqueIndexerFunc) UniqueIndex { + return UniqueIndex{ + MultiKeyIndex: newIndex(builder, prefix, NewUniqueIndexer(uniqueIndexerFunc, builder.IndexKeyCodec())), + } +} + +// indexIterator uses rowGetter to lazy load new model values on request. +type indexIterator struct { + ctx HasKVStore + rowGetter RowGetter + it types.Iterator + keyCodec IndexKeyCodec +} + +// LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there +// are no more items the ErrIteratorDone error is returned +// The key is the rowID and not any MultiKeyIndex key. +func (i indexIterator) LoadNext(dest codec.ProtoMarshaler) (RowID, error) { + if !i.it.Valid() { + return nil, ErrIteratorDone + } + indexPrefixKey := i.it.Key() + rowID := i.keyCodec.StripRowID(indexPrefixKey) + i.it.Next() + return rowID, i.rowGetter(i.ctx, rowID, dest) +} + +// Close releases the iterator and should be called at the end of iteration +func (i indexIterator) Close() error { + i.it.Close() + return nil +} + +// PrefixRange turns a prefix into a (start, end) range. The start is the given prefix value and +// the end is calculated by adding 1 bit to the start value. Nil is not allowed as prefix. +// Example: []byte{1, 3, 4} becomes []byte{1, 3, 5} +// []byte{15, 42, 255, 255} becomes []byte{15, 43, 0, 0} +// +// In case of an overflow the end is set to nil. +// Example: []byte{255, 255, 255, 255} becomes nil +// +func PrefixRange(prefix []byte) ([]byte, []byte) { + if prefix == nil { + panic("nil key not allowed") + } + // special case: no prefix is whole range + if len(prefix) == 0 { + return nil, nil + } + + // copy the prefix and update last byte + end := make([]byte, len(prefix)) + copy(end, prefix) + l := len(end) - 1 + end[l]++ + + // wait, what if that overflowed?.... + for end[l] == 0 && l > 0 { + l-- + end[l]++ + } + + // okay, funny guy, you gave us FFF, no end to this range... + if l == 0 && end[0] == 0 { + end = nil + } + return prefix, end +} diff --git a/regen/orm/index_key_codec.go b/regen/orm/index_key_codec.go new file mode 100644 index 0000000000..8ef01ab041 --- /dev/null +++ b/regen/orm/index_key_codec.go @@ -0,0 +1,68 @@ +package orm + +// Max255DynamicLengthIndexKeyCodec works with up to 255 byte dynamic size RowIDs. +// They are encoded as `concat(searchableKey, rowID, len(rowID)[0])` and can be used +// with PrimaryKey or external Key tables for example. +type Max255DynamicLengthIndexKeyCodec struct{} + +// BuildIndexKey builds the index key by appending searchableKey with rowID and length int. +// The RowID length must not be greater than 255. +func (Max255DynamicLengthIndexKeyCodec) BuildIndexKey(searchableKey []byte, rowID RowID) []byte { + rowIDLen := len(rowID) + switch { + case rowIDLen == 0: + panic("Empty RowID") + case rowIDLen > 255: + panic("RowID exceeds max size") + } + + searchableKeyLen := len(searchableKey) + res := make([]byte, searchableKeyLen+rowIDLen+1) + copy(res, searchableKey) + copy(res[searchableKeyLen:], rowID) + res[searchableKeyLen+rowIDLen] = byte(rowIDLen) + return res +} + +// StripRowID returns the RowID from the combined persistentIndexKey. It is the reverse operation to BuildIndexKey +// but with the searchableKey and length int dropped. +func (Max255DynamicLengthIndexKeyCodec) StripRowID(persistentIndexKey []byte) RowID { + n := len(persistentIndexKey) + searchableKeyLen := persistentIndexKey[n-1] + return persistentIndexKey[n-int(searchableKeyLen)-1 : n-1] +} + +// FixLengthIndexKeyCodec expects the RowID to always have the same length with all entries. +// They are encoded as `concat(searchableKey, rowID)` and can be used +// with AutoUint64Tables and length EncodedSeqLength for example. +type FixLengthIndexKeyCodec struct { + rowIDLength int +} + +// FixLengthIndexKeys is a constructor for FixLengthIndexKeyCodec. +func FixLengthIndexKeys(rowIDLength int) *FixLengthIndexKeyCodec { + return &FixLengthIndexKeyCodec{rowIDLength: rowIDLength} +} + +// BuildIndexKey builds the index key by appending searchableKey with rowID. +// The RowID length must not be greater than what is defined by rowIDLength in construction. +func (c FixLengthIndexKeyCodec) BuildIndexKey(searchableKey []byte, rowID RowID) []byte { + switch n := len(rowID); { + case n == 0: + panic("Empty RowID") + case n > c.rowIDLength: + panic("RowID exceeds max size") + } + n := len(searchableKey) + res := make([]byte, n+c.rowIDLength) + copy(res, searchableKey) + copy(res[n:], rowID) + return res +} + +// StripRowID returns the RowID from the combined persistentIndexKey. It is the reverse operation to BuildIndexKey +// but with the searchableKey dropped. +func (c FixLengthIndexKeyCodec) StripRowID(persistentIndexKey []byte) RowID { + n := len(persistentIndexKey) + return persistentIndexKey[n-c.rowIDLength:] +} diff --git a/regen/orm/index_key_codec_test.go b/regen/orm/index_key_codec_test.go new file mode 100644 index 0000000000..d7f49df545 --- /dev/null +++ b/regen/orm/index_key_codec_test.go @@ -0,0 +1,115 @@ +package orm + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestEncodeIndexKey(t *testing.T) { + specs := map[string]struct { + srcKey []byte + srcRowID RowID + enc IndexKeyCodec + expKey []byte + expPanic bool + }{ + "dynamic length example 1": { + srcKey: []byte{0x0, 0x1, 0x2}, + srcRowID: []byte{0x3, 0x4}, + enc: Max255DynamicLengthIndexKeyCodec{}, + expKey: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x2}, + }, + "dynamic length example 2": { + srcKey: []byte{0x0, 0x1}, + srcRowID: []byte{0x2, 0x3, 0x4}, + enc: Max255DynamicLengthIndexKeyCodec{}, + expKey: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x3}, + }, + "dynamic length max row ID": { + srcKey: []byte{0x0, 0x1}, + srcRowID: []byte(strings.Repeat("a", 255)), + enc: Max255DynamicLengthIndexKeyCodec{}, + expKey: append(append([]byte{0x0, 0x1}, []byte(strings.Repeat("a", 255))...), 0xff), + }, + "dynamic length panics with empty rowID": { + srcKey: []byte{0x0, 0x1}, + srcRowID: []byte{}, + enc: Max255DynamicLengthIndexKeyCodec{}, + expPanic: true, + }, + "dynamic length exceeds max row ID": { + srcKey: []byte{0x0, 0x1}, + srcRowID: []byte(strings.Repeat("a", 256)), + enc: Max255DynamicLengthIndexKeyCodec{}, + expPanic: true, + }, + "uint64 example": { + srcKey: []byte{0x0, 0x1, 0x2}, + srcRowID: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}, + enc: FixLengthIndexKeys(8), + expKey: []byte{0x0, 0x1, 0x2, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}, + }, + "uint64 panics with empty rowID": { + srcKey: []byte{0x0, 0x1}, + srcRowID: []byte{}, + enc: FixLengthIndexKeys(8), + expPanic: true, + }, + "uint64 exceeds max bytes in rowID": { + srcKey: []byte{0x0, 0x1}, + srcRowID: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9}, + enc: FixLengthIndexKeys(8), + expPanic: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + if spec.expPanic { + require.Panics(t, + func() { + _ = spec.enc.BuildIndexKey(spec.srcKey, spec.srcRowID) + }) + return + } + got := spec.enc.BuildIndexKey(spec.srcKey, spec.srcRowID) + assert.Equal(t, spec.expKey, got) + }) + } +} +func TestDecodeIndexKey(t *testing.T) { + specs := map[string]struct { + srcKey []byte + enc IndexKeyCodec + expRowID RowID + }{ + "dynamic length example 1": { + srcKey: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x2}, + enc: Max255DynamicLengthIndexKeyCodec{}, + expRowID: []byte{0x3, 0x4}, + }, + "dynamic length example 2": { + srcKey: []byte{0x0, 0x1, 0x2, 0x3, 0x4, 0x3}, + enc: Max255DynamicLengthIndexKeyCodec{}, + expRowID: []byte{0x2, 0x3, 0x4}, + }, + "dynamic length max row ID": { + srcKey: append(append([]byte{0x0, 0x1}, []byte(strings.Repeat("a", 255))...), 0xff), + enc: Max255DynamicLengthIndexKeyCodec{}, + expRowID: []byte(strings.Repeat("a", 255)), + }, + "uint64 example": { + srcKey: []byte{0x0, 0x1, 0x2, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}, + expRowID: []byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}, + enc: FixLengthIndexKeys(8), + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + gotRow := spec.enc.StripRowID(spec.srcKey) + assert.Equal(t, spec.expRowID, gotRow) + }) + } +} diff --git a/regen/orm/index_test.go b/regen/orm/index_test.go new file mode 100644 index 0000000000..2becc94f99 --- /dev/null +++ b/regen/orm/index_test.go @@ -0,0 +1,348 @@ +package orm_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestIndexPrefixScan(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + storeKey := sdk.NewKVStoreKey("test") + const ( + testTablePrefix = iota + testTableSeqPrefix + ) + tBuilder := orm.NewAutoUInt64TableBuilder(testTablePrefix, testTableSeqPrefix, storeKey, &testdata.GroupInfo{}, cdc) + idx := orm.NewIndex(tBuilder, GroupByAdminIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + return []orm.RowID{[]byte(val.(*testdata.GroupInfo).Admin)}, nil + }) + tb := tBuilder.Build() + ctx := orm.NewMockContext() + + g1 := testdata.GroupInfo{ + Description: "my test 1", + Admin: sdk.AccAddress([]byte("admin-address-a")), + } + g2 := testdata.GroupInfo{ + Description: "my test 2", + Admin: sdk.AccAddress([]byte("admin-address-b")), + } + g3 := testdata.GroupInfo{ + Description: "my test 3", + Admin: sdk.AccAddress([]byte("admin-address-b")), + } + for _, g := range []testdata.GroupInfo{g1, g2, g3} { + _, err := tb.Create(ctx, &g) + require.NoError(t, err) + } + + specs := map[string]struct { + start, end []byte + expResult []testdata.GroupInfo + expRowIDs []orm.RowID + expError *errors.Error + method func(ctx orm.HasKVStore, start, end []byte) (orm.Iterator, error) + }{ + "exact match with a single result": { + start: []byte("admin-address-a"), + end: []byte("admin-address-b"), + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "one result by prefix": { + start: []byte("admin-address"), + end: []byte("admin-address-b"), + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "multi key elements by exact match": { + start: []byte("admin-address-b"), + end: []byte("admin-address-c"), + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "open end query": { + start: []byte("admin-address-b"), + end: nil, + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "open start query": { + start: nil, + end: []byte("admin-address-b"), + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "open start and end query": { + start: nil, + end: nil, + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g1, g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1), orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "all matching prefix": { + start: []byte("admin"), + end: nil, + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{g1, g2, g3}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1), orm.EncodeSequence(2), orm.EncodeSequence(3)}, + }, + "non matching prefix": { + start: []byte("nobody"), + end: nil, + method: idx.PrefixScan, + expResult: []testdata.GroupInfo{}, + }, + "start equals end": { + start: []byte("any"), + end: []byte("any"), + method: idx.PrefixScan, + expError: orm.ErrArgument, + }, + "start after end": { + start: []byte("b"), + end: []byte("a"), + method: idx.PrefixScan, + expError: orm.ErrArgument, + }, + "reverse: exact match with a single result": { + start: []byte("admin-address-a"), + end: []byte("admin-address-b"), + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "reverse: one result by prefix": { + start: []byte("admin-address"), + end: []byte("admin-address-b"), + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "reverse: multi key elements by exact match": { + start: []byte("admin-address-b"), + end: []byte("admin-address-c"), + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2)}, + }, + "reverse: open end query": { + start: []byte("admin-address-b"), + end: nil, + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2)}, + }, + "reverse: open start query": { + start: nil, + end: []byte("admin-address-b"), + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(1)}, + }, + "reverse: open start and end query": { + start: nil, + end: nil, + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2, g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2), orm.EncodeSequence(1)}, + }, + "reverse: all matching prefix": { + start: []byte("admin"), + end: nil, + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{g3, g2, g1}, + expRowIDs: []orm.RowID{orm.EncodeSequence(3), orm.EncodeSequence(2), orm.EncodeSequence(1)}, + }, + "reverse: non matching prefix": { + start: []byte("nobody"), + end: nil, + method: idx.ReversePrefixScan, + expResult: []testdata.GroupInfo{}, + }, + "reverse: start equals end": { + start: []byte("any"), + end: []byte("any"), + method: idx.ReversePrefixScan, + expError: orm.ErrArgument, + }, + "reverse: start after end": { + start: []byte("b"), + end: []byte("a"), + method: idx.ReversePrefixScan, + expError: orm.ErrArgument, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + it, err := spec.method(ctx, spec.start, spec.end) + require.True(t, spec.expError.Is(err), "expected #+v but got #+v", spec.expError, err) + if spec.expError != nil { + return + } + var loaded []testdata.GroupInfo + rowIDs, err := orm.ReadAll(it, &loaded) + require.NoError(t, err) + assert.Equal(t, spec.expResult, loaded) + assert.Equal(t, spec.expRowIDs, rowIDs) + }) + } +} + +func TestUniqueIndex(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + + tableBuilder := orm.NewPrimaryKeyTableBuilder(GroupMemberTablePrefix, storeKey, &testdata.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + uniqueIdx := orm.NewUniqueIndex(tableBuilder, 0x10, func(val interface{}) (orm.RowID, error) { + return []byte{val.(*testdata.GroupMember).Member[0]}, nil + }) + myTable := tableBuilder.Build() + + ctx := orm.NewMockContext() + + m := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("member-address")), + Weight: 10, + } + err := myTable.Create(ctx, &m) + require.NoError(t, err) + + indexedKey := []byte{byte('m')} + + // Has + assert.True(t, uniqueIdx.Has(ctx, indexedKey)) + + // Get + it, err := uniqueIdx.Get(ctx, indexedKey) + require.NoError(t, err) + var loaded testdata.GroupMember + rowID, err := it.LoadNext(&loaded) + require.NoError(t, err) + require.Equal(t, orm.RowID(orm.PrimaryKey(&m)), rowID) + require.Equal(t, m, loaded) + + // GetPaginated + cases := map[string]struct { + pageReq *query.PageRequest + expErr bool + }{ + "nil key": { + pageReq: &query.PageRequest{Key: nil}, + expErr: false, + }, + "after indexed key": { + pageReq: &query.PageRequest{Key: indexedKey}, + expErr: true, + }, + } + + for testName, tc := range cases { + t.Run(testName, func(t *testing.T) { + it, err := uniqueIdx.GetPaginated(ctx, indexedKey, tc.pageReq) + require.NoError(t, err) + rowID, err := it.LoadNext(&loaded) + if tc.expErr { // iterator done + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, orm.RowID(orm.PrimaryKey(&m)), rowID) + require.Equal(t, m, loaded) + } + }) + } + + // PrefixScan match + it, err = uniqueIdx.PrefixScan(ctx, []byte{byte('m')}, []byte{byte('n')}) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.NoError(t, err) + require.Equal(t, orm.RowID(orm.PrimaryKey(&m)), rowID) + require.Equal(t, m, loaded) + + // PrefixScan no match + it, err = uniqueIdx.PrefixScan(ctx, []byte{byte('n')}, nil) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.Error(t, orm.ErrIteratorDone, err) + + // ReversePrefixScan match + it, err = uniqueIdx.ReversePrefixScan(ctx, []byte{byte('a')}, []byte{byte('z')}) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.NoError(t, err) + require.Equal(t, orm.RowID(orm.PrimaryKey(&m)), rowID) + require.Equal(t, m, loaded) + + // ReversePrefixScan no match + it, err = uniqueIdx.ReversePrefixScan(ctx, []byte{byte('l')}, nil) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.Error(t, orm.ErrIteratorDone, err) + // create with same index key should fail + new := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("my-other")), + Weight: 10, + } + err = myTable.Create(ctx, &new) + require.Error(t, orm.ErrUniqueConstraint, err) + + // and when delete + err = myTable.Delete(ctx, &m) + require.NoError(t, err) + + // then no persistent element + assert.False(t, uniqueIdx.Has(ctx, indexedKey)) +} + +func TestPrefixRange(t *testing.T) { + cases := map[string]struct { + src []byte + expStart []byte + expEnd []byte + expPanic bool + }{ + "normal": {src: []byte{1, 3, 4}, expStart: []byte{1, 3, 4}, expEnd: []byte{1, 3, 5}}, + "normal short": {src: []byte{79}, expStart: []byte{79}, expEnd: []byte{80}}, + "empty case": {src: []byte{}}, + "roll-over example 1": {src: []byte{17, 28, 255}, expStart: []byte{17, 28, 255}, expEnd: []byte{17, 29, 0}}, + "roll-over example 2": {src: []byte{15, 42, 255, 255}, expStart: []byte{15, 42, 255, 255}, expEnd: []byte{15, 43, 0, 0}}, + "pathological roll-over": {src: []byte{255, 255, 255, 255}, expStart: []byte{255, 255, 255, 255}}, + "nil prohibited": {expPanic: true}, + } + + for testName, tc := range cases { + t.Run(testName, func(t *testing.T) { + if tc.expPanic { + require.Panics(t, func() { + orm.PrefixRange(tc.src) + }) + return + } + start, end := orm.PrefixRange(tc.src) + assert.Equal(t, tc.expStart, start) + assert.Equal(t, tc.expEnd, end) + }) + } +} diff --git a/regen/orm/indexer.go b/regen/orm/indexer.go new file mode 100644 index 0000000000..b02307b353 --- /dev/null +++ b/regen/orm/indexer.go @@ -0,0 +1,158 @@ +package orm + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// IndexerFunc creates one or multiple index keys for the source object. +type IndexerFunc func(value interface{}) ([]RowID, error) + +// IndexerFunc creates exactly one index key for the source object. +type UniqueIndexerFunc func(value interface{}) (RowID, error) + +// Indexer manages the persistence for an Index based on searchable keys and operations. +type Indexer struct { + indexerFunc IndexerFunc + addFunc func(store sdk.KVStore, codec IndexKeyCodec, secondaryIndexKey []byte, rowID RowID) error + indexKeyCodec IndexKeyCodec +} + +// NewIndexer returns an indexer that supports multiple reference keys for an entity. +func NewIndexer(indexerFunc IndexerFunc, codec IndexKeyCodec) *Indexer { + if indexerFunc == nil { + panic("Indexer func must not be nil") + } + if codec == nil { + panic("IndexKeyCodec must not be nil") + } + return &Indexer{ + indexerFunc: pruneEmptyKeys(indexerFunc), + addFunc: multiKeyAddFunc, + indexKeyCodec: codec, + } +} + +// NewUniqueIndexer returns an indexer that requires exactly one reference keys for an entity. +func NewUniqueIndexer(f UniqueIndexerFunc, codec IndexKeyCodec) *Indexer { + if f == nil { + panic("indexer func must not be nil") + } + adaptor := func(indexerFunc UniqueIndexerFunc) IndexerFunc { + return func(v interface{}) ([]RowID, error) { + k, err := indexerFunc(v) + return []RowID{k}, err + } + } + idx := NewIndexer(adaptor(f), codec) + idx.addFunc = uniqueKeysAddFunc + return idx +} + +// OnCreate persists the secondary index entries for the new object. +func (i Indexer) OnCreate(store sdk.KVStore, rowID RowID, value interface{}) error { + secondaryIndexKeys, err := i.indexerFunc(value) + if err != nil { + return err + } + + for _, secondaryIndexKey := range secondaryIndexKeys { + if err := i.addFunc(store, i.indexKeyCodec, secondaryIndexKey, rowID); err != nil { + return err + } + } + return nil +} + +// OnDelete removes the secondary index entries for the deleted object. +func (i Indexer) OnDelete(store sdk.KVStore, rowID RowID, value interface{}) error { + secondaryIndexKeys, err := i.indexerFunc(value) + if err != nil { + return err + } + + for _, secondaryIndexKey := range secondaryIndexKeys { + indexKey := i.indexKeyCodec.BuildIndexKey(secondaryIndexKey, rowID) + store.Delete(indexKey) + } + return nil +} + +// OnUpdate rebuilds the secondary index entries for the updated object. +func (i Indexer) OnUpdate(store sdk.KVStore, rowID RowID, newValue, oldValue interface{}) error { + oldSecIdxKeys, err := i.indexerFunc(oldValue) + if err != nil { + return err + } + newSecIdxKeys, err := i.indexerFunc(newValue) + if err != nil { + return err + } + for _, oldIdxKey := range difference(oldSecIdxKeys, newSecIdxKeys) { + store.Delete(i.indexKeyCodec.BuildIndexKey(oldIdxKey, rowID)) + } + for _, newIdxKey := range difference(newSecIdxKeys, oldSecIdxKeys) { + if err := i.addFunc(store, i.indexKeyCodec, newIdxKey, rowID); err != nil { + return err + } + } + return nil +} + +// uniqueKeysAddFunc enforces keys to be unique +func uniqueKeysAddFunc(store sdk.KVStore, codec IndexKeyCodec, secondaryIndexKey []byte, rowID RowID) error { + if len(secondaryIndexKey) == 0 { + return errors.Wrap(ErrArgument, "empty index key") + } + it := store.Iterator(PrefixRange(secondaryIndexKey)) + defer it.Close() + if it.Valid() { + return ErrUniqueConstraint + } + indexKey := codec.BuildIndexKey(secondaryIndexKey, rowID) + store.Set(indexKey, []byte{}) + return nil +} + +// multiKeyAddFunc allows multiple entries for a key +func multiKeyAddFunc(store sdk.KVStore, codec IndexKeyCodec, secondaryIndexKey []byte, rowID RowID) error { + if len(secondaryIndexKey) == 0 { + return errors.Wrap(ErrArgument, "empty index key") + } + + indexKey := codec.BuildIndexKey(secondaryIndexKey, rowID) + store.Set(indexKey, []byte{}) + return nil +} + +// difference returns the list of elements that are in a but not in b. +func difference(a []RowID, b []RowID) []RowID { + set := make(map[string]struct{}, len(b)) + for _, v := range b { + set[string(v)] = struct{}{} + } + var result []RowID + for _, v := range a { + if _, ok := set[string(v)]; !ok { + result = append(result, v) + } + } + return result +} + +// pruneEmptyKeys drops any empty key from IndexerFunc f returned +func pruneEmptyKeys(f IndexerFunc) IndexerFunc { + return func(v interface{}) ([]RowID, error) { + keys, err := f(v) + if err != nil || keys == nil { + return keys, err + } + r := make([]RowID, 0, len(keys)) + for i := range keys { + if len(keys[i]) != 0 { + r = append(r, keys[i]) + } + } + return r, nil + } +} diff --git a/regen/orm/indexer_test.go b/regen/orm/indexer_test.go new file mode 100644 index 0000000000..05843181e2 --- /dev/null +++ b/regen/orm/indexer_test.go @@ -0,0 +1,527 @@ +package orm + +import ( + stdErrors "errors" + "testing" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestIndexerOnCreate(t *testing.T) { + var myRowID RowID = EncodeSequence(1) + + specs := map[string]struct { + srcFunc IndexerFunc + expIndexKeys []RowID + expRowIDs []RowID + expAddFuncCalled bool + expErr error + }{ + "single key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{0, 0, 0, 0, 0, 0, 0, 1}}, nil + }, + expAddFuncCalled: true, + expIndexKeys: []RowID{{0, 0, 0, 0, 0, 0, 0, 1}}, + expRowIDs: []RowID{myRowID}, + }, + "multi key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0}}, nil + }, + expAddFuncCalled: true, + expIndexKeys: []RowID{{0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0}}, + expRowIDs: []RowID{myRowID, myRowID}, + }, + "empty key in slice": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{}}, nil + }, + expAddFuncCalled: false, + }, + "nil key in slice": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{nil}, nil + }, + expAddFuncCalled: false, + }, + "empty key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{}, nil + }, + expAddFuncCalled: false, + }, + "nil key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return nil, nil + }, + expAddFuncCalled: false, + }, + "error case": { + srcFunc: func(value interface{}) ([]RowID, error) { + return nil, stdErrors.New("test") + }, + expErr: stdErrors.New("test"), + expAddFuncCalled: false, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + mockPolicy := &addFuncRecorder{} + idx := NewIndexer(spec.srcFunc, Max255DynamicLengthIndexKeyCodec{}) + idx.addFunc = mockPolicy.add + + err := idx.OnCreate(nil, myRowID, nil) + if spec.expErr != nil { + require.Equal(t, spec.expErr, err) + return + } + require.NoError(t, err) + assert.Equal(t, spec.expIndexKeys, mockPolicy.secondaryIndexKeys) + assert.Equal(t, spec.expRowIDs, mockPolicy.rowIDs) + assert.Equal(t, spec.expAddFuncCalled, mockPolicy.called) + }) + } +} + +func TestIndexerOnDelete(t *testing.T) { + myRowID := EncodeSequence(1) + + var multiKeyIndex MultiKeyIndex + ctx := NewMockContext() + storeKey := sdk.NewKVStoreKey("test") + store := prefix.NewStore(ctx.KVStore(storeKey), []byte{multiKeyIndex.prefix}) + + specs := map[string]struct { + srcFunc IndexerFunc + expIndexKeys []RowID + expErr error + }{ + "single key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{0, 0, 0, 0, 0, 0, 0, 1}}, nil + }, + expIndexKeys: []RowID{append([]byte{0, 0, 0, 0, 0, 0, 0, 1}, myRowID...)}, + }, + "multi key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0}}, nil + }, + expIndexKeys: []RowID{ + append([]byte{0, 0, 0, 0, 0, 0, 0, 1}, myRowID...), + append([]byte{1, 0, 0, 0, 0, 0, 0, 0}, myRowID...), + }, + }, + "empty key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{}, nil + }, + }, + "nil key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return nil, nil + }, + }, + "empty key in slice": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{}}, nil + }, + }, + "nil key in slice": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{nil}, nil + }, + }, + "error case": { + srcFunc: func(value interface{}) ([]RowID, error) { + return nil, stdErrors.New("test") + }, + expErr: stdErrors.New("test"), + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + codec := FixLengthIndexKeys(EncodedSeqLength) + idx := NewIndexer(spec.srcFunc, codec) + err := idx.OnDelete(store, myRowID, nil) + if spec.expErr != nil { + require.Equal(t, spec.expErr, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestIndexerOnUpdate(t *testing.T) { + myRowID := EncodeSequence(1) + codec := FixLengthIndexKeys(EncodedSeqLength) + + var multiKeyIndex MultiKeyIndex + ctx := NewMockContext() + storeKey := sdk.NewKVStoreKey("test") + store := prefix.NewStore(ctx.KVStore(storeKey), []byte{multiKeyIndex.prefix}) + + specs := map[string]struct { + srcFunc IndexerFunc + mockStore *updateKVStoreRecorder + expAddedKeys []RowID + expDeletedKeys []RowID + expErr error + addFunc func(sdk.KVStore, IndexKeyCodec, []byte, RowID) error + }{ + "single key - same key, no update": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{EncodeSequence(1)}, nil + }, + }, + "single key - different key, replaced": { + srcFunc: func(value interface{}) ([]RowID, error) { + keys := []RowID{EncodeSequence(1), EncodeSequence(2)} + return []RowID{keys[value.(int)]}, nil + }, + expAddedKeys: []RowID{ + append(EncodeSequence(2), myRowID...), + }, + expDeletedKeys: []RowID{ + append(EncodeSequence(1), myRowID...), + }, + }, + "multi key - same key, no update": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{EncodeSequence(1), EncodeSequence(2)}, nil + }, + }, + "multi key - replaced": { + srcFunc: func(value interface{}) ([]RowID, error) { + keys := []RowID{EncodeSequence(1), EncodeSequence(2), EncodeSequence(3), EncodeSequence(4)} + return []RowID{keys[value.(int)], keys[value.(int)+2]}, nil + }, + expAddedKeys: []RowID{ + append(EncodeSequence(2), myRowID...), + append(EncodeSequence(4), myRowID...), + }, + expDeletedKeys: []RowID{ + append(EncodeSequence(1), myRowID...), + append(EncodeSequence(3), myRowID...), + }, + }, + "empty key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{}, nil + }, + }, + "nil key": { + srcFunc: func(value interface{}) ([]RowID, error) { + return nil, nil + }, + }, + "empty key in slice": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{{}}, nil + }, + }, + "nil key in slice": { + srcFunc: func(value interface{}) ([]RowID, error) { + return []RowID{nil}, nil + }, + }, + "error case with new value": { + srcFunc: func(value interface{}) ([]RowID, error) { + return nil, stdErrors.New("test") + }, + expErr: stdErrors.New("test"), + }, + "error case with old value": { + srcFunc: func(value interface{}) ([]RowID, error) { + var err error + if value.(int)%2 == 1 { + err = stdErrors.New("test") + } + return []RowID{myRowID}, err + }, + expErr: stdErrors.New("test"), + }, + "error case on persisting new keys": { + srcFunc: func(value interface{}) ([]RowID, error) { + keys := []RowID{EncodeSequence(1), EncodeSequence(2)} + return []RowID{keys[value.(int)]}, nil + }, + addFunc: func(_ sdk.KVStore, _ IndexKeyCodec, _ []byte, _ RowID) error { + return stdErrors.New("test") + }, + expErr: stdErrors.New("test"), + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + idx := NewIndexer(spec.srcFunc, codec) + if spec.addFunc != nil { + idx.addFunc = spec.addFunc + } + err := idx.OnUpdate(store, myRowID, 1, 0) + if spec.expErr != nil { + require.Equal(t, spec.expErr, err) + return + } + require.NoError(t, err) + + }) + } +} + +func TestUniqueKeyAddFunc(t *testing.T) { + myRowID := EncodeSequence(1) + myPresetKey := append([]byte("my-preset-key"), myRowID...) + + specs := map[string]struct { + srcKey []byte + expErr *errors.Error + expExistingEntry []byte + }{ + + "create when not exists": { + srcKey: []byte("my-index-key"), + expExistingEntry: append([]byte("my-index-key"), myRowID...), + }, + "error when exists already": { + srcKey: []byte("my-preset-key"), + expErr: ErrUniqueConstraint, + }, + "nil key not allowed": { + srcKey: nil, + expErr: ErrArgument, + }, + "empty key not allowed": { + srcKey: []byte{}, + expErr: ErrArgument, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + storeKey := sdk.NewKVStoreKey("test") + store := NewMockContext().KVStore(storeKey) + store.Set(myPresetKey, []byte{}) + + codec := FixLengthIndexKeys(EncodedSeqLength) + err := uniqueKeysAddFunc(store, codec, spec.srcKey, myRowID) + require.True(t, spec.expErr.Is(err)) + if spec.expErr != nil { + return + } + assert.True(t, store.Has(spec.expExistingEntry), "not found") + }) + } +} + +func TestMultiKeyAddFunc(t *testing.T) { + myRowID := EncodeSequence(1) + myPresetKey := append([]byte("my-preset-key"), myRowID...) + + specs := map[string]struct { + srcKey []byte + expErr *errors.Error + expExistingEntry []byte + }{ + + "create when not exists": { + srcKey: []byte("my-index-key"), + expExistingEntry: append([]byte("my-index-key"), myRowID...), + }, + "noop when exists already": { + srcKey: []byte("my-preset-key"), + expExistingEntry: myPresetKey, + }, + "nil key not allowed": { + srcKey: nil, + expErr: ErrArgument, + }, + "empty key not allowed": { + srcKey: []byte{}, + expErr: ErrArgument, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + storeKey := sdk.NewKVStoreKey("test") + store := NewMockContext().KVStore(storeKey) + store.Set(myPresetKey, []byte{}) + + codec := FixLengthIndexKeys(EncodedSeqLength) + err := multiKeyAddFunc(store, codec, spec.srcKey, myRowID) + require.True(t, spec.expErr.Is(err)) + if spec.expErr != nil { + return + } + assert.True(t, store.Has(spec.expExistingEntry)) + }) + } +} + +func TestDifference(t *testing.T) { + asByte := func(s []string) []RowID { + r := make([]RowID, len(s)) + for i := 0; i < len(s); i++ { + r[i] = []byte(s[i]) + } + return r + } + + specs := map[string]struct { + srcA []string + srcB []string + expResult []RowID + }{ + "all of A": { + srcA: []string{"a", "b"}, + srcB: []string{"c"}, + expResult: []RowID{[]byte("a"), []byte("b")}, + }, + "A - B": { + srcA: []string{"a", "b"}, + srcB: []string{"b", "c", "d"}, + expResult: []RowID{[]byte("a")}, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + got := difference(asByte(spec.srcA), asByte(spec.srcB)) + assert.Equal(t, spec.expResult, got) + }) + } +} + +func TestPruneEmptyKeys(t *testing.T) { + specs := map[string]struct { + srcFunc IndexerFunc + expResult []RowID + expError error + }{ + "non empty": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{{0}, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "empty": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{}, nil + }, + expResult: []RowID{}, + }, + "nil": { + srcFunc: func(v interface{}) ([]RowID, error) { + return nil, nil + }, + }, + "nil in the beginning": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{nil, {0}, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "nil in the middle": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{{0}, nil, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "nil at the end": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{{0}, nil, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "empty in the beginning": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{{}, {0}, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "empty in the middle": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{{0}, {}, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "empty at the end": { + srcFunc: func(v interface{}) ([]RowID, error) { + return []RowID{{0}, {}, {1}}, nil + }, + expResult: []RowID{{0}, {1}}, + }, + "error passed": { + srcFunc: func(v interface{}) ([]RowID, error) { + return nil, stdErrors.New("test") + }, + expError: stdErrors.New("test"), + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + r, err := pruneEmptyKeys(spec.srcFunc)(nil) + require.Equal(t, spec.expError, err) + if spec.expError != nil { + return + } + assert.Equal(t, spec.expResult, r) + }) + } +} + +type addFuncRecorder struct { + secondaryIndexKeys []RowID + rowIDs []RowID + called bool +} + +func (c *addFuncRecorder) add(_ sdk.KVStore, _ IndexKeyCodec, key []byte, rowID RowID) error { + c.secondaryIndexKeys = append(c.secondaryIndexKeys, key) + c.rowIDs = append(c.rowIDs, rowID) + c.called = true + return nil +} + +type deleteKVStoreRecorder struct { + AlwaysPanicKVStore + deletes []RowID +} + +func (m *deleteKVStoreRecorder) Delete(key []byte) { + m.deletes = append(m.deletes, key) +} + +type updateKVStoreRecorder struct { + deleteKVStoreRecorder + stored tuples + hasResult bool +} + +func (u *updateKVStoreRecorder) Set(key, value []byte) { + u.stored = append(u.stored, tuple{key, value}) +} + +func (u updateKVStoreRecorder) Has(key []byte) bool { + return u.hasResult +} + +type tuple struct { + key, val []byte +} + +type tuples []tuple + +func (t tuples) Keys() []RowID { + if t == nil { + return nil + } + r := make([]RowID, len(t)) + for i, v := range t { + r[i] = v.key + } + return r +} diff --git a/regen/orm/iterator.go b/regen/orm/iterator.go new file mode 100644 index 0000000000..234cb39791 --- /dev/null +++ b/regen/orm/iterator.go @@ -0,0 +1,304 @@ +package orm + +import ( + "fmt" + "reflect" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" +) + +// IteratorFunc is a function type that satisfies the Iterator interface +// The passed function is called on LoadNext operations. +type IteratorFunc func(dest codec.ProtoMarshaler) (RowID, error) + +// LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there +// are no more items the ErrIteratorDone error is returned +// The key is the rowID and not any MultiKeyIndex key. +func (i IteratorFunc) LoadNext(dest codec.ProtoMarshaler) (RowID, error) { + return i(dest) +} + +// Close always returns nil +func (i IteratorFunc) Close() error { + return nil +} + +func NewSingleValueIterator(rowID RowID, val []byte) Iterator { + var closed bool + return IteratorFunc(func(dest codec.ProtoMarshaler) (RowID, error) { + if dest == nil { + return nil, errors.Wrap(ErrArgument, "destination object must not be nil") + } + if closed || val == nil { + return nil, ErrIteratorDone + } + closed = true + return rowID, dest.Unmarshal(val) + }) +} + +// Iterator that return ErrIteratorInvalid only. +func NewInvalidIterator() Iterator { + return IteratorFunc(func(dest codec.ProtoMarshaler) (RowID, error) { + return nil, ErrIteratorInvalid + }) +} + +// LimitedIterator returns up to defined maximum number of elements. +type LimitedIterator struct { + remainingCount int + parentIterator Iterator +} + +// LimitIterator returns a new iterator that returns max number of elements. +// The parent iterator must not be nil +// max can be 0 or any positive number +func LimitIterator(parent Iterator, max int) *LimitedIterator { + if max < 0 { + panic("quantity must not be negative") + } + if parent == nil { + panic("parent iterator must not be nil") + } + return &LimitedIterator{remainingCount: max, parentIterator: parent} +} + +// LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there +// are no more items or the defined max number of elements was returned the `ErrIteratorDone` error is returned +// The key is the rowID and not any MultiKeyIndex key. +func (i *LimitedIterator) LoadNext(dest codec.ProtoMarshaler) (RowID, error) { + if i.remainingCount == 0 { + return nil, ErrIteratorDone + } + i.remainingCount-- + return i.parentIterator.LoadNext(dest) +} + +// Close releases the iterator and should be called at the end of iteration +func (i LimitedIterator) Close() error { + return i.parentIterator.Close() +} + +// First loads the first element into the given destination type and closes the iterator. +// When the iterator is closed or has no elements the according error is passed as return value. +func First(it Iterator, dest codec.ProtoMarshaler) (RowID, error) { + if it == nil { + return nil, errors.Wrap(ErrArgument, "iterator must not be nil") + } + defer it.Close() + binKey, err := it.LoadNext(dest) + if err != nil { + return nil, err + } + return binKey, nil +} + +// Paginate does pagination with a given Iterator based on the provided +// PageRequest and unmarshals the results into the dest interface that must be +// an non-nil pointer to a slice. +// +// If pageRequest is nil, then we will use these default values: +// - Offset: 0 +// - Key: nil +// - Limit: 100 +// - CountTotal: true +// +// If pageRequest.Key was provided, it got used beforehand to instantiate the Iterator, +// using for instance UInt64Index.GetPaginated method. Only one of pageRequest.Offset or +// pageRequest.Key should be set. Using pageRequest.Key is more efficient for querying +// the next page. +// +// If pageRequest.CountTotal is set, we'll visit all iterators elements. +// pageRequest.CountTotal is only respected when offset is used. +// +// This function will call it.Close(). +func Paginate( + it Iterator, + pageRequest *query.PageRequest, + dest ModelSlicePtr, +) (*query.PageResponse, error) { + // if the PageRequest is nil, use default PageRequest + if pageRequest == nil { + pageRequest = &query.PageRequest{} + } + + offset := pageRequest.Offset + key := pageRequest.Key + limit := pageRequest.Limit + countTotal := pageRequest.CountTotal + + if offset > 0 && key != nil { + return nil, fmt.Errorf("invalid request, either offset or key is expected, got both") + } + + if limit == 0 { + limit = 100 + + // count total results when the limit is zero/not supplied + countTotal = true + } + + if it == nil { + return nil, errors.Wrap(ErrArgument, "iterator must not be nil") + } + defer it.Close() + + var destRef, tmpSlice reflect.Value + elemType, err := assertDest(dest, &destRef, &tmpSlice) + if err != nil { + return nil, err + } + + var end = offset + limit + var count uint64 + var nextKey []byte + for { + obj := reflect.New(elemType) + val := obj.Elem() + model := obj + if elemType.Kind() == reflect.Ptr { + val.Set(reflect.New(elemType.Elem())) + // if elemType is already a pointer (e.g. dest being some pointer to a slice of pointers, + // like []*GroupMember), then obj is a pointer to a pointer which might cause issues + // if we try to do obj.Interface().(codec.ProtoMarshaler). + // For that reason, we copy obj into model if we have a simple pointer + // but in case elemType.Kind() == reflect.Ptr, we overwrite it with model = val + // so we can safely call model.Interface().(codec.ProtoMarshaler) afterwards. + model = val + } + + modelProto, ok := model.Interface().(codec.ProtoMarshaler) + if !ok { + return nil, errors.Wrapf(ErrArgument, "%s should implement codec.ProtoMarshaler", elemType) + } + binKey, err := it.LoadNext(modelProto) + if err != nil { + if ErrIteratorDone.Is(err) { + break + } + return nil, err + } + + count++ + + // During the first loop, count value at this point will be 1, + // so if offset is >= 1, it will continue to load the next value until count > offset + // else (offset = 0, key might be set or not), + // it will start to append values to tmpSlice. + if count <= offset { + continue + } + + if count <= end { + tmpSlice = reflect.Append(tmpSlice, val) + } else if count == end+1 { + nextKey = binKey + + // countTotal is set to true to indicate that the result set should include + // a count of the total number of items available for pagination in UIs. + // countTotal is only respected when offset is used. It is ignored when key + // is set. + if !countTotal || len(key) != 0 { + break + } + } + } + destRef.Set(tmpSlice) + + res := &query.PageResponse{NextKey: nextKey} + if countTotal && len(key) == 0 { + res.Total = count + } + + return res, nil +} + +// ModelSlicePtr represents a pointer to a slice of models. Think of it as +// *[]Model Because of Go's type system, using []Model type would not work for us. +// Instead we use a placeholder type and the validation is done during the +// runtime. +type ModelSlicePtr interface{} + +// ReadAll consumes all values for the iterator and stores them in a new slice at the passed ModelSlicePtr. +// The slice can be empty when the iterator does not return any values but not nil. The iterator +// is closed afterwards. +// Example: +// var loaded []testdata.GroupInfo +// rowIDs, err := ReadAll(it, &loaded) +// require.NoError(t, err) +// +func ReadAll(it Iterator, dest ModelSlicePtr) ([]RowID, error) { + if it == nil { + return nil, errors.Wrap(ErrArgument, "iterator must not be nil") + } + defer it.Close() + + var destRef, tmpSlice reflect.Value + elemType, err := assertDest(dest, &destRef, &tmpSlice) + if err != nil { + return nil, err + } + + var rowIDs []RowID + for { + obj := reflect.New(elemType) + val := obj.Elem() + model := obj + if elemType.Kind() == reflect.Ptr { + val.Set(reflect.New(elemType.Elem())) + model = val + } + + binKey, err := it.LoadNext(model.Interface().(codec.ProtoMarshaler)) + switch { + case err == nil: + tmpSlice = reflect.Append(tmpSlice, val) + case ErrIteratorDone.Is(err): + destRef.Set(tmpSlice) + return rowIDs, nil + default: + return nil, err + } + rowIDs = append(rowIDs, binKey) + } +} + +// assertDest checks that the provided dest is not nil and a pointer to a slice. +// It also verifies that the slice elements implement *codec.ProtoMarshaler. +// It overwrites destRef and tmpSlice using reflection. +func assertDest(dest ModelSlicePtr, destRef *reflect.Value, tmpSlice *reflect.Value) (reflect.Type, error) { + if dest == nil { + return nil, errors.Wrap(ErrArgument, "destination must not be nil") + } + tp := reflect.ValueOf(dest) + if tp.Kind() != reflect.Ptr { + return nil, errors.Wrap(ErrArgument, "destination must be a pointer to a slice") + } + if tp.Elem().Kind() != reflect.Slice { + return nil, errors.Wrap(ErrArgument, "destination must point to a slice") + } + + // Since dest is just an interface{}, we overwrite destRef using reflection + // to have an assignable copy of it. + *destRef = tp.Elem() + // We need to verify that we can call Set() on destRef. + if !destRef.CanSet() { + return nil, errors.Wrap(ErrArgument, "destination not assignable") + } + + elemType := reflect.TypeOf(dest).Elem().Elem() + + protoMarshaler := reflect.TypeOf((*codec.ProtoMarshaler)(nil)).Elem() + if !elemType.Implements(protoMarshaler) && + !reflect.PtrTo(elemType).Implements(protoMarshaler) { + return nil, errors.Wrapf(ErrArgument, "unsupported type :%s", elemType) + } + + // tmpSlice is a slice value for the specified type + // that we'll use for appending new elements. + *tmpSlice = reflect.MakeSlice(reflect.SliceOf(elemType), 0, 0) + + return elemType, nil +} diff --git a/regen/orm/iterator_test.go b/regen/orm/iterator_test.go new file mode 100644 index 0000000000..cfd2372b39 --- /dev/null +++ b/regen/orm/iterator_test.go @@ -0,0 +1,263 @@ +package orm_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestReadAll(t *testing.T) { + specs := map[string]struct { + srcIT orm.Iterator + destSlice func() orm.ModelSlicePtr + expErr *errors.Error + expIDs []orm.RowID + expResult orm.ModelSlicePtr + }{ + "all good with object slice": { + srcIT: mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{Description: "test"}), + destSlice: func() orm.ModelSlicePtr { + x := make([]testdata.GroupInfo, 1) + return &x + }, + expIDs: []orm.RowID{orm.EncodeSequence(1)}, + expResult: &[]testdata.GroupInfo{{Description: "test"}}, + }, + "all good with pointer slice": { + srcIT: mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{Description: "test"}), + destSlice: func() orm.ModelSlicePtr { + x := make([]*testdata.GroupInfo, 1) + return &x + }, + expIDs: []orm.RowID{orm.EncodeSequence(1)}, + expResult: &[]*testdata.GroupInfo{{Description: "test"}}, + }, + "dest slice empty": { + srcIT: mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{}), + destSlice: func() orm.ModelSlicePtr { + x := make([]testdata.GroupInfo, 0) + return &x + }, + expIDs: []orm.RowID{orm.EncodeSequence(1)}, + expResult: &[]testdata.GroupInfo{{}}, + }, + "dest pointer with nil value": { + srcIT: mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{}), + destSlice: func() orm.ModelSlicePtr { + return (*[]testdata.GroupInfo)(nil) + }, + expErr: orm.ErrArgument, + }, + "iterator is nil": { + srcIT: nil, + destSlice: func() orm.ModelSlicePtr { return new([]testdata.GroupInfo) }, + expErr: orm.ErrArgument, + }, + "dest slice is nil": { + srcIT: noopIter(), + destSlice: func() orm.ModelSlicePtr { return nil }, + expErr: orm.ErrArgument, + }, + "dest slice is not a pointer": { + srcIT: orm.IteratorFunc(nil), + destSlice: func() orm.ModelSlicePtr { return make([]testdata.GroupInfo, 1) }, + expErr: orm.ErrArgument, + }, + "error on loadNext is returned": { + srcIT: orm.NewInvalidIterator(), + destSlice: func() orm.ModelSlicePtr { + x := make([]testdata.GroupInfo, 1) + return &x + }, + expErr: orm.ErrIteratorInvalid, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + loaded := spec.destSlice() + ids, err := orm.ReadAll(spec.srcIT, loaded) + require.True(t, spec.expErr.Is(err), "expected %s but got %s", spec.expErr, err) + assert.Equal(t, spec.expIDs, ids) + if err == nil { + assert.Equal(t, spec.expResult, loaded) + } + }) + } +} + +func TestLimitedIterator(t *testing.T) { + specs := map[string]struct { + src orm.Iterator + exp []testdata.GroupInfo + }{ + "all from range with max > length": { + src: orm.LimitIterator(mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{Description: "test"}), 2), + exp: []testdata.GroupInfo{{Description: "test"}}, + }, + "up to max": { + src: orm.LimitIterator(mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{Description: "test"}), 1), + exp: []testdata.GroupInfo{{Description: "test"}}, + }, + "none when max = 0": { + src: orm.LimitIterator(mockIter(orm.EncodeSequence(1), &testdata.GroupInfo{Description: "test"}), 0), + exp: []testdata.GroupInfo{}, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + var loaded []testdata.GroupInfo + _, err := orm.ReadAll(spec.src, &loaded) + require.NoError(t, err) + assert.EqualValues(t, spec.exp, loaded) + }) + } +} + +func TestPaginate(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const ( + testTablePrefix = iota + testTableSeqPrefix + ) + tBuilder := orm.NewAutoUInt64TableBuilder(testTablePrefix, testTableSeqPrefix, storeKey, &testdata.GroupInfo{}, cdc) + idx := orm.NewIndex(tBuilder, GroupByAdminIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + return []orm.RowID{[]byte(val.(*testdata.GroupInfo).Admin)}, nil + }) + tb := tBuilder.Build() + ctx := orm.NewMockContext() + + admin := sdk.AccAddress([]byte("admin-address")) + g1 := testdata.GroupInfo{ + Description: "my test 1", + Admin: admin, + } + g2 := testdata.GroupInfo{ + Description: "my test 2", + Admin: admin, + } + g3 := testdata.GroupInfo{ + Description: "my test 3", + Admin: sdk.AccAddress([]byte("other-admin-address")), + } + g4 := testdata.GroupInfo{ + Description: "my test 4", + Admin: admin, + } + g5 := testdata.GroupInfo{ + Description: "my test 5", + Admin: sdk.AccAddress([]byte("other-admin-address")), + } + + for _, g := range []testdata.GroupInfo{g1, g2, g3, g4, g5} { + _, err := tb.Create(ctx, &g) + require.NoError(t, err) + } + + specs := map[string]struct { + pageReq *query.PageRequest + expPageRes *query.PageResponse + exp []testdata.GroupInfo + key []byte + expErr bool + }{ + "one item": { + pageReq: &query.PageRequest{Key: nil, Limit: 1}, + exp: []testdata.GroupInfo{g1}, + expPageRes: &query.PageResponse{Total: 0, NextKey: orm.EncodeSequence(2)}, + key: admin, + }, + "with both key and offset": { + pageReq: &query.PageRequest{Key: orm.EncodeSequence(2), Offset: 1}, + expErr: true, + key: admin, + }, + "up to max": { + pageReq: &query.PageRequest{Key: nil, Limit: 3, CountTotal: true}, + exp: []testdata.GroupInfo{g1, g2, g4}, + expPageRes: &query.PageResponse{Total: 3, NextKey: nil}, + key: admin, + }, + "no results": { + pageReq: &query.PageRequest{Key: nil, Limit: 2, CountTotal: true}, + exp: []testdata.GroupInfo{}, + expPageRes: &query.PageResponse{Total: 0, NextKey: nil}, + key: sdk.AccAddress([]byte("no-group-address")), + }, + "with offset and count total": { + pageReq: &query.PageRequest{Key: nil, Offset: 1, Limit: 2, CountTotal: true}, + exp: []testdata.GroupInfo{g2, g4}, + expPageRes: &query.PageResponse{Total: 3, NextKey: nil}, + key: admin, + }, + "nil/default page req (limit = 100 > number of items)": { + pageReq: nil, + exp: []testdata.GroupInfo{g1, g2, g4}, + expPageRes: &query.PageResponse{Total: 3, NextKey: nil}, + key: admin, + }, + "with key and limit < number of elem (count total is ignored in this case)": { + pageReq: &query.PageRequest{Key: orm.EncodeSequence(2), Limit: 1, CountTotal: true}, + exp: []testdata.GroupInfo{g2}, + expPageRes: &query.PageResponse{Total: 0, NextKey: orm.EncodeSequence(4)}, + key: admin, + }, + "with key and limit >= number of elem": { + pageReq: &query.PageRequest{Key: orm.EncodeSequence(2), Limit: 2}, + exp: []testdata.GroupInfo{g2, g4}, + expPageRes: &query.PageResponse{Total: 0, NextKey: nil}, + key: admin, + }, + "with nothing left to iterate from key": { + pageReq: &query.PageRequest{Key: orm.EncodeSequence(5)}, + exp: []testdata.GroupInfo{}, + expPageRes: &query.PageResponse{Total: 0, NextKey: nil}, + key: admin, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + var loaded []testdata.GroupInfo + + it, err := idx.GetPaginated(ctx, spec.key, spec.pageReq) + require.NoError(t, err) + + res, err := orm.Paginate(it, spec.pageReq, &loaded) + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + assert.EqualValues(t, spec.exp, loaded) + assert.EqualValues(t, spec.expPageRes.Total, res.Total) + assert.EqualValues(t, spec.expPageRes.NextKey, res.NextKey) + } + + }) + } +} + +// mockIter amino encodes + decodes value object. +func mockIter(rowID orm.RowID, val codec.ProtoMarshaler) orm.Iterator { + b, err := val.Marshal() + if err != nil { + panic(err) + } + return orm.NewSingleValueIterator(rowID, b) +} + +func noopIter() orm.Iterator { + return orm.IteratorFunc(func(dest codec.ProtoMarshaler) (orm.RowID, error) { + return nil, nil + }) +} diff --git a/regen/orm/orm.go b/regen/orm/orm.go new file mode 100644 index 0000000000..1797d9228e --- /dev/null +++ b/regen/orm/orm.go @@ -0,0 +1,177 @@ +/* +Package orm is a convenient object to data store mapper. +*/ +package orm + +import ( + "io" + "reflect" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" +) + +const ormCodespace = "orm" + +var ( + ErrNotFound = errors.Register(ormCodespace, 100, "not found") + ErrIteratorDone = errors.Register(ormCodespace, 101, "iterator done") + ErrIteratorInvalid = errors.Register(ormCodespace, 102, "iterator invalid") + ErrType = errors.Register(ormCodespace, 110, "invalid type") + ErrUniqueConstraint = errors.Register(ormCodespace, 111, "unique constraint violation") + ErrArgument = errors.Register(ormCodespace, 112, "invalid argument") + ErrIndexKeyMaxLength = errors.Register(ormCodespace, 113, "index key exceeds max length") + ErrEmptyKey = errors.Register(ormCodespace, 114, "cannot use empty key") +) + +// HasKVStore is a subset of the cosmos-sdk context defined for loose coupling and simpler test setups. +type HasKVStore interface { + KVStore(key sdk.StoreKey) sdk.KVStore +} + +// Unique identifier of a persistent table. +type RowID []byte + +// Bytes returns raw bytes. +func (r RowID) Bytes() []byte { + return r +} + +// Validateable is an interface that Persistent types can implement and is called on any orm save or update operation. +type Validateable interface { + // ValidateBasic is a sanity check on the data. Any error returned prevents create or updates. + ValidateBasic() error +} + +// Persistent supports Marshal and Unmarshal +// +// This is separated from Marshal, as this almost always requires +// a pointer, and functions that only need to marshal bytes can +// use the Marshaller interface to access non-pointers. +// +// As with Marshaller, this may do internal validation on the data +// and errors should be expected. +type Persistent interface { + // Marshal serializes object into binary representation + Marshal() ([]byte, error) + // Unmarshal deserializes the object from the binary representation + Unmarshal([]byte) error +} + +// Index allows efficient prefix scans is stored as key = concat(indexKeyBytes, rowIDUint64) with value empty +// so that the row PrimaryKey is allows a fixed with 8 byte integer. This allows the MultiKeyIndex key bytes to be +// variable length and scanned iteratively. The +type Index interface { + // Has checks if a key exists. Panics on nil key. + Has(ctx HasKVStore, key []byte) bool + + // Get returns a result iterator for the searchKey. + // searchKey must not be nil. + Get(ctx HasKVStore, searchKey []byte) (Iterator, error) + + // GetPaginated returns a result iterator for the searchKey and optional pageRequest. + // searchKey must not be nil. + GetPaginated(ctx HasKVStore, searchKey []byte, pageRequest *query.PageRequest) (Iterator, error) + + // PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. + // Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. + // Iterator must be closed by caller. + // To iterate over entire domain, use PrefixScan(nil, nil) + // + // WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose + // this as an endpoint to the public without further limits. + // Example: + // it, err := idx.PrefixScan(ctx, start, end) + // if err !=nil { + // return err + // } + // const defaultLimit = 20 + // it = LimitIterator(it, defaultLimit) + // + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + PrefixScan(ctx HasKVStore, start []byte, end []byte) (Iterator, error) + + // ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. + // Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. + // Iterator must be closed by caller. + // To iterate over entire domain, use PrefixScan(nil, nil) + // + // WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose + // this as an endpoint to the public without further limits. See `LimitIterator` + // + // CONTRACT: No writes may happen within a domain while an iterator exists over it. + ReversePrefixScan(ctx HasKVStore, start []byte, end []byte) (Iterator, error) +} + +// Iterator allows iteration through a sequence of key value pairs +type Iterator interface { + // LoadNext loads the next value in the sequence into the pointer passed as dest and returns the key. If there + // are no more items the ErrIteratorDone error is returned + // The key is the rowID and not any MultiKeyIndex key. + LoadNext(dest codec.ProtoMarshaler) (RowID, error) + // Close releases the iterator and should be called at the end of iteration + io.Closer +} + +// IndexKeyCodec defines the encoding/ decoding methods for building/ splitting index keys. +type IndexKeyCodec interface { + // BuildIndexKey encodes a searchable key and the target RowID. + BuildIndexKey(searchableKey []byte, rowID RowID) []byte + // StripRowID returns the RowID from the combined persistentIndexKey. It is the reverse operation to BuildIndexKey + // but with the searchableKey dropped. + StripRowID(persistentIndexKey []byte) RowID +} + +// Indexable types are used to setup new tables. +// This interface provides a set of functions that can be called by indexes to register and interact with the tables. +type Indexable interface { + StoreKey() sdk.StoreKey + RowGetter() RowGetter + IndexKeyCodec() IndexKeyCodec + AddAfterSaveInterceptor(interceptor AfterSaveInterceptor) + AddAfterDeleteInterceptor(interceptor AfterDeleteInterceptor) +} + +// AfterSaveInterceptor defines a callback function to be called on Create + Update. +type AfterSaveInterceptor func(ctx HasKVStore, rowID RowID, newValue, oldValue codec.ProtoMarshaler) error + +// AfterDeleteInterceptor defines a callback function to be called on Delete operations. +type AfterDeleteInterceptor func(ctx HasKVStore, rowID RowID, value codec.ProtoMarshaler) error + +// RowGetter loads a persistent object by row ID into the destination object. The dest parameter must therefore be a pointer. +// Any implementation must return `ErrNotFound` when no object for the rowID exists +type RowGetter func(ctx HasKVStore, rowID RowID, dest codec.ProtoMarshaler) error + +// NewTypeSafeRowGetter returns a `RowGetter` with type check on the dest parameter. +func NewTypeSafeRowGetter(storeKey sdk.StoreKey, prefixKey byte, model reflect.Type, cdc codec.Codec) RowGetter { + return func(ctx HasKVStore, rowID RowID, dest codec.ProtoMarshaler) error { + if len(rowID) == 0 { + return errors.Wrap(ErrArgument, "key must not be nil") + } + if err := assertCorrectType(model, dest); err != nil { + return err + } + + store := prefix.NewStore(ctx.KVStore(storeKey), []byte{prefixKey}) + it := store.Iterator(PrefixRange(rowID)) + defer it.Close() + if !it.Valid() { + return ErrNotFound + } + return cdc.Unmarshal(it.Value(), dest) + } +} + +func assertCorrectType(model reflect.Type, obj codec.ProtoMarshaler) error { + tp := reflect.TypeOf(obj) + if tp.Kind() != reflect.Ptr { + return errors.Wrap(ErrType, "model destination must be a pointer") + } + if model != tp.Elem() { + return errors.Wrapf(ErrType, "can not use %T with this bucket", obj) + } + return nil +} diff --git a/regen/orm/orm_scenario_test.go b/regen/orm/orm_scenario_test.go new file mode 100644 index 0000000000..68ee52bb2c --- /dev/null +++ b/regen/orm/orm_scenario_test.go @@ -0,0 +1,405 @@ +package orm_test + +import ( + "bytes" + "encoding/binary" + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +// Testing ORM with arbitrary address length +const addrLen = 10 + +func TestKeeperEndToEndWithAutoUInt64Table(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + ctx := orm.NewMockContext() + + k := NewGroupKeeper(storeKey, cdc) + + g := testdata.GroupInfo{ + GroupId: 1, + Description: "my test", + Admin: sdk.AccAddress([]byte("admin-address")), + } + // when stored + rowID, err := k.groupTable.Create(ctx, &g) + require.NoError(t, err) + // then we should find it + exists := k.groupTable.Has(ctx, rowID) + require.True(t, exists) + + // and load it + var loaded testdata.GroupInfo + + binKey, err := k.groupTable.GetOne(ctx, rowID, &loaded) + require.NoError(t, err) + + assert.Equal(t, rowID, binary.BigEndian.Uint64(binKey)) + assert.Equal(t, "my test", loaded.Description) + assert.Equal(t, sdk.AccAddress([]byte("admin-address")), loaded.Admin) + + // and exists in MultiKeyIndex + exists = k.groupByAdminIndex.Has(ctx, []byte("admin-address")) + require.True(t, exists) + + // and when loaded + it, err := k.groupByAdminIndex.Get(ctx, []byte("admin-address")) + require.NoError(t, err) + + // then + binKey, loaded = first(t, it) + assert.Equal(t, rowID, binary.BigEndian.Uint64(binKey)) + assert.Equal(t, g, loaded) + + // when updated + g.Admin = []byte("new-admin-address") + err = k.groupTable.Save(ctx, rowID, &g) + require.NoError(t, err) + + // then indexes are updated, too + exists = k.groupByAdminIndex.Has(ctx, []byte("new-admin-address")) + require.True(t, exists) + + exists = k.groupByAdminIndex.Has(ctx, []byte("admin-address")) + require.False(t, exists) + + // when deleted + err = k.groupTable.Delete(ctx, rowID) + require.NoError(t, err) + + // then removed from primary MultiKeyIndex + exists = k.groupTable.Has(ctx, rowID) + require.False(t, exists) + + // and also removed from secondary MultiKeyIndex + exists = k.groupByAdminIndex.Has(ctx, []byte("new-admin-address")) + require.False(t, exists) +} + +func TestKeeperEndToEndWithPrimaryKeyTable(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + ctx := orm.NewMockContext() + + k := NewGroupKeeper(storeKey, cdc) + + g := testdata.GroupInfo{ + GroupId: 1, + Description: "my test", + Admin: sdk.AccAddress([]byte("admin-address")), + } + + m := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("member-address")), + Weight: 10, + } + groupRowID, err := k.groupTable.Create(ctx, &g) + require.NoError(t, err) + require.Equal(t, uint64(1), groupRowID) + // when stored + err = k.groupMemberTable.Create(ctx, &m) + require.NoError(t, err) + + // then we should find it by primary key + primaryKey := orm.PrimaryKey(&m) + exists := k.groupMemberTable.Has(ctx, primaryKey) + require.True(t, exists) + // and load it by primary key + var loaded testdata.GroupMember + err = k.groupMemberTable.GetOne(ctx, primaryKey, &loaded) + require.NoError(t, err) + + // then values should match expectations + require.Equal(t, m, loaded) + + // and then the data should exists in MultiKeyIndex + exists = k.groupMemberByGroupIndex.Has(ctx, orm.EncodeSequence(groupRowID)) + require.True(t, exists) + + // and when loaded from MultiKeyIndex + it, err := k.groupMemberByGroupIndex.Get(ctx, orm.EncodeSequence(groupRowID)) + require.NoError(t, err) + + // then values should match as before + _, err = orm.First(it, &loaded) + require.NoError(t, err) + + assert.Equal(t, m, loaded) + // and when we create another entry with the same primary key + err = k.groupMemberTable.Create(ctx, &m) + // then it should fail as the primary key must be unique + require.True(t, orm.ErrUniqueConstraint.Is(err), err) + + // and when entity updated with new primary key + updatedMember := &testdata.GroupMember{ + Group: m.Group, + Member: []byte("new-member-address"), + Weight: m.Weight, + } + // then it should fail as the primary key is immutable + err = k.groupMemberTable.Save(ctx, updatedMember) + require.Error(t, err) + + // and when entity updated with non primary key attribute modified + updatedMember = &testdata.GroupMember{ + Group: m.Group, + Member: m.Member, + Weight: 99, + } + // then it should not fail + err = k.groupMemberTable.Save(ctx, updatedMember) + require.NoError(t, err) + + // and when entity deleted + err = k.groupMemberTable.Delete(ctx, &m) + require.NoError(t, err) + + // then it is removed from primary key MultiKeyIndex + exists = k.groupMemberTable.Has(ctx, primaryKey) + require.False(t, exists) + + // and removed from secondary MultiKeyIndex + exists = k.groupMemberByGroupIndex.Has(ctx, orm.EncodeSequence(groupRowID)) + require.False(t, exists) +} + +func TestGasCostsPrimaryKeyTable(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + ctx := orm.NewMockContext() + + k := NewGroupKeeper(storeKey, cdc) + + g := testdata.GroupInfo{ + GroupId: 1, + Description: "my test", + Admin: sdk.AccAddress([]byte("admin-address")), + } + + m := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("member-address")), + Weight: 10, + } + groupRowID, err := k.groupTable.Create(ctx, &g) + require.NoError(t, err) + require.Equal(t, uint64(1), groupRowID) + gCtx := orm.NewGasCountingMockContext(ctx) + err = k.groupMemberTable.Create(gCtx, &m) + require.NoError(t, err) + t.Logf("gas consumed on create: %d", gCtx.GasConsumed()) + + // get by primary key + gCtx.ResetGasMeter() + var loaded testdata.GroupMember + err = k.groupMemberTable.GetOne(gCtx, orm.PrimaryKey(&m), &loaded) + require.NoError(t, err) + t.Logf("gas consumed on get by primary key: %d", gCtx.GasConsumed()) + + // get by secondary index + gCtx.ResetGasMeter() + // and when loaded from MultiKeyIndex + it, err := k.groupMemberByGroupIndex.Get(gCtx, orm.EncodeSequence(groupRowID)) + require.NoError(t, err) + var loadedSlice []testdata.GroupMember + _, err = orm.ReadAll(it, &loadedSlice) + require.NoError(t, err) + + t.Logf("gas consumed on get by multi index key: %d", gCtx.GasConsumed()) + + // delete + gCtx.ResetGasMeter() + err = k.groupMemberTable.Delete(gCtx, &m) + require.NoError(t, err) + t.Logf("gas consumed on delete by primary key: %d", gCtx.GasConsumed()) + + // with 3 elements + for i := 1; i < 4; i++ { + gCtx.ResetGasMeter() + m := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte(fmt.Sprintf("member-address%d", i))), + Weight: 10, + } + err = k.groupMemberTable.Create(gCtx, &m) + require.NoError(t, err) + t.Logf("%d: gas consumed on create: %d", i, gCtx.GasConsumed()) + } + + for i := 1; i < 4; i++ { + gCtx.ResetGasMeter() + m := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte(fmt.Sprintf("member-address%d", i))), + Weight: 10, + } + err = k.groupMemberTable.GetOne(gCtx, orm.PrimaryKey(&m), &loaded) + require.NoError(t, err) + t.Logf("%d: gas consumed on get by primary key: %d", i, gCtx.GasConsumed()) + } + + // get by secondary index + gCtx.ResetGasMeter() + // and when loaded from MultiKeyIndex + it, err = k.groupMemberByGroupIndex.Get(gCtx, orm.EncodeSequence(groupRowID)) + require.NoError(t, err) + _, err = orm.ReadAll(it, &loadedSlice) + require.NoError(t, err) + require.Len(t, loadedSlice, 3) + t.Logf("gas consumed on get by multi index key: %d", gCtx.GasConsumed()) + + // delete + for i, m := range loadedSlice { + gCtx.ResetGasMeter() + + err = k.groupMemberTable.Delete(gCtx, &m) + require.NoError(t, err) + t.Logf("%d: gas consumed on delete: %d", i, gCtx.GasConsumed()) + } +} + +func TestExportImportStateAutoUInt64Table(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + ctx := orm.NewMockContext() + + k := NewGroupKeeper(storeKey, cdc) + + testRecords := 10 + for i := 1; i <= testRecords; i++ { + myAddr := sdk.AccAddress(bytes.Repeat([]byte{byte(i)}, addrLen)) + g := testdata.GroupInfo{ + GroupId: uint64(i), + Description: fmt.Sprintf("my test %d", i), + Admin: myAddr, + } + + groupRowID, err := k.groupTable.Create(ctx, &g) + require.NoError(t, err) + require.Equal(t, uint64(i), groupRowID) + } + var groups []*testdata.GroupInfo + seqVal, err := orm.ExportTableData(ctx, k.groupTable, &groups) + require.NoError(t, err) + + // when a new db seeded + ctx = orm.NewMockContext() + + err = orm.ImportTableData(ctx, k.groupTable, groups, seqVal) + require.NoError(t, err) + // then all data is set again + + for i := 1; i <= testRecords; i++ { + require.True(t, k.groupTable.Has(ctx, uint64(i))) + var loaded testdata.GroupInfo + groupRowID, err := k.groupTable.GetOne(ctx, uint64(i), &loaded) + require.NoError(t, err) + + require.Equal(t, orm.RowID(orm.EncodeSequence(uint64(i))), groupRowID) + assert.Equal(t, fmt.Sprintf("my test %d", i), loaded.Description) + exp := sdk.AccAddress(bytes.Repeat([]byte{byte(i)}, addrLen)) + assert.Equal(t, exp, loaded.Admin) + + // and also the indexes + require.True(t, k.groupByAdminIndex.Has(ctx, exp)) + it, err := k.groupByAdminIndex.Get(ctx, exp) + require.NoError(t, err) + var all []testdata.GroupInfo + orm.ReadAll(it, &all) + require.Len(t, all, 1) + assert.Equal(t, loaded, all[0]) + } + require.Equal(t, uint64(testRecords), k.groupTable.Sequence().CurVal(ctx)) +} + +func TestExportImportStatePrimaryKeyTable(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + ctx := orm.NewMockContext() + + k := NewGroupKeeper(storeKey, cdc) + myGroupAddr := sdk.AccAddress(bytes.Repeat([]byte{byte('a')}, addrLen)) + testRecordsNum := 10 + testRecords := make([]testdata.GroupMember, testRecordsNum) + for i := 1; i <= testRecordsNum; i++ { + myAddr := sdk.AccAddress(bytes.Repeat([]byte{byte(i)}, addrLen)) + g := testdata.GroupMember{ + Group: myGroupAddr, + Member: myAddr, + Weight: uint64(i), + } + err := k.groupMemberTable.Create(ctx, &g) + require.NoError(t, err) + testRecords[i-1] = g + } + var groupMembers []*testdata.GroupMember + _, err := orm.ExportTableData(ctx, k.groupMemberTable, &groupMembers) + require.NoError(t, err) + + // when a new db seeded + ctx = orm.NewMockContext() + + err = orm.ImportTableData(ctx, k.groupMemberTable, groupMembers, 0) + require.NoError(t, err) + + // then all data is set again + it, err := k.groupMemberTable.PrefixScan(ctx, nil, nil) + require.NoError(t, err) + var loaded []testdata.GroupMember + keys, err := orm.ReadAll(it, &loaded) + require.NoError(t, err) + for i := range keys { + assert.Equal(t, orm.PrimaryKey(&testRecords[i]), keys[i].Bytes()) + } + assert.Equal(t, testRecords, loaded) + + // and first index setup + it, err = k.groupMemberByGroupIndex.Get(ctx, myGroupAddr) + require.NoError(t, err) + loaded = nil + keys, err = orm.ReadAll(it, &loaded) + require.NoError(t, err) + for i := range keys { + assert.Equal(t, orm.PrimaryKey(&testRecords[i]), keys[i].Bytes()) + } + assert.Equal(t, testRecords, loaded) + + // and second index setup + for _, v := range testRecords { + it, err = k.groupMemberByMemberIndex.Get(ctx, v.Member) + require.NoError(t, err) + loaded = nil + keys, err = orm.ReadAll(it, &loaded) + require.NoError(t, err) + assert.Equal(t, []orm.RowID{orm.PrimaryKey(&v)}, keys) + assert.Equal(t, []testdata.GroupMember{v}, loaded) + } +} + +func first(t *testing.T, it orm.Iterator) ([]byte, testdata.GroupInfo) { + var loaded testdata.GroupInfo + key, err := orm.First(it, &loaded) + require.NoError(t, err) + return key, loaded +} diff --git a/regen/orm/orm_test.go b/regen/orm/orm_test.go new file mode 100644 index 0000000000..6f97274b5d --- /dev/null +++ b/regen/orm/orm_test.go @@ -0,0 +1,77 @@ +package orm_test + +import ( + "reflect" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestTypeSafeRowGetter(t *testing.T) { + storeKey := sdk.NewKVStoreKey("test") + ctx := orm.NewMockContext() + const prefixKey = 0x2 + store := prefix.NewStore(ctx.KVStore(storeKey), []byte{prefixKey}) + md := testdata.GroupInfo{Description: "foo"} + bz, err := md.Marshal() + require.NoError(t, err) + store.Set(orm.EncodeSequence(1), bz) + + specs := map[string]struct { + srcRowID orm.RowID + srcModelType reflect.Type + expObj interface{} + expErr *errors.Error + }{ + "happy path": { + srcRowID: orm.EncodeSequence(1), + srcModelType: reflect.TypeOf(testdata.GroupInfo{}), + expObj: testdata.GroupInfo{Description: "foo"}, + }, + "unknown rowID should return ErrNotFound": { + srcRowID: orm.EncodeSequence(999), + srcModelType: reflect.TypeOf(testdata.GroupInfo{}), + expErr: orm.ErrNotFound, + }, + "wrong type should cause ErrType": { + srcRowID: orm.EncodeSequence(1), + srcModelType: reflect.TypeOf(testdata.GroupMember{}), + expErr: orm.ErrType, + }, + "empty rowID not allowed": { + srcRowID: []byte{}, + srcModelType: reflect.TypeOf(testdata.GroupInfo{}), + expErr: orm.ErrArgument, + }, + "nil rowID not allowed": { + srcModelType: reflect.TypeOf(testdata.GroupInfo{}), + expErr: orm.ErrArgument, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + getter := orm.NewTypeSafeRowGetter(storeKey, prefixKey, spec.srcModelType, cdc) + var loadedObj testdata.GroupInfo + + err := getter(ctx, spec.srcRowID, &loadedObj) + if spec.expErr != nil { + require.True(t, spec.expErr.Is(err), err) + return + } + require.NoError(t, err) + assert.Equal(t, spec.expObj, loadedObj) + }) + } +} diff --git a/regen/orm/primary_key.go b/regen/orm/primary_key.go new file mode 100644 index 0000000000..0c3499c8cb --- /dev/null +++ b/regen/orm/primary_key.go @@ -0,0 +1,208 @@ +package orm + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var _ Indexable = &PrimaryKeyTableBuilder{} + +// NewPrimaryKeyTableBuilder creates a builder to setup a PrimaryKeyTable object. +func NewPrimaryKeyTableBuilder(prefixData byte, storeKey sdk.StoreKey, model PrimaryKeyed, codec IndexKeyCodec, cdc codec.Codec) *PrimaryKeyTableBuilder { + return &PrimaryKeyTableBuilder{ + tableBuilder: newTableBuilder(prefixData, storeKey, model, codec, cdc), + } +} + +type PrimaryKeyTableBuilder struct { + *tableBuilder +} + +func (a PrimaryKeyTableBuilder) Build() PrimaryKeyTable { + return PrimaryKeyTable{table: a.tableBuilder.Build()} + +} + +// PrimaryKeyed defines an object type that is aware of its immutable primary key. +type PrimaryKeyed interface { + // PrimaryKeyFields returns the fields of the object that will make up + // the primary key. The PrimaryKey function will encode and concatenate + // the fields to build the primary key. + // + // PrimaryKey parts can be []byte, string, and integer types. []byte is + // encoded with a length prefix, strings are null-terminated, and + // integers are encoded using 4 or 8 byte big endian. + // + // IMPORTANT: []byte parts are encoded with a single byte length prefix, + // so cannot be longer than 256 bytes. + // + // The `IndexKeyCodec` used with the `PrimaryKeyTable` may add certain + // constraints to the byte representation as max length = 255 in + // `Max255DynamicLengthIndexKeyCodec` or a fix length in + // `FixLengthIndexKeyCodec` for example. + PrimaryKeyFields() []interface{} + codec.ProtoMarshaler +} + +// PrimaryKey returns the immutable and serialized primary key of this object. +// The primary key has to be unique within it's domain so that not two with same +// value can exist in the same table. This means PrimaryKeyFields() has to +// return a unique value for each object. +// +// PrimaryKey parts can be []byte, string, and integer types. The function will panic if +// it there is a part of any other type. +// []byte is encoded with a length prefix, strings are null-terminated, and integers are +// encoded using 4 or 8 byte big endian. +// The function panics if obj.PrimaryKey contains an +func PrimaryKey(obj PrimaryKeyed) []byte { + fields := obj.PrimaryKeyFields() + return buildPrimaryKey(fields) +} + +// buildPrimaryKey encodes and concatenates the PrimaryKeyFields. See PrimaryKey +// for full documentation of the encoding. +// fields must have elements of type []byte, string or integer. If it contains other type +// the the function will panic. +func buildPrimaryKey(fields []interface{}) []byte { + bytesSlice := make([][]byte, len(fields)) + totalLen := 0 + for i, field := range fields { + bytesSlice[i] = primaryKeyFieldBytes(field) + totalLen += len(bytesSlice[i]) + } + primaryKey := make([]byte, 0, totalLen) + for _, bs := range bytesSlice { + primaryKey = append(primaryKey, bs...) + } + return primaryKey +} + +func primaryKeyFieldBytes(field interface{}) []byte { + switch v := field.(type) { + case []byte: + return AddLengthPrefix(v) + case string: + return NullTerminatedBytes(v) + case uint64: + return EncodeSequence(v) + default: + panic(fmt.Sprintf("Type %T not allowed as primary key field", v)) + } +} + +// Prefix the byte array with its length as 8 bytes. The function will panic +// if the bytes length is bigger than 256. +func AddLengthPrefix(bytes []byte) []byte { + byteLen := len(bytes) + if byteLen > 256 { + panic("Cannot create primary key with an []byte of length greater than 256 bytes. Try again with a smaller []byte.") + } + + prefixedBytes := make([]byte, 1+len(bytes)) + copy(prefixedBytes, []byte{uint8(byteLen)}) + copy(prefixedBytes[1:], bytes) + return prefixedBytes +} + +// Convert string to byte array and null terminate it +func NullTerminatedBytes(s string) []byte { + bytes := make([]byte, len(s)+1) + copy(bytes, s) + return bytes +} + +var _ TableExportable = &PrimaryKeyTable{} + +// PrimaryKeyTable provides simpler object style orm methods without passing database RowIDs. +// Entries are persisted and loaded with a reference to their unique primary key. +type PrimaryKeyTable struct { + table table +} + +// Create persists the given object under their primary key. It checks if the +// key already exists and may return an `ErrUniqueConstraint`. +// Create iterates though the registered callbacks and may add secondary index keys by them. +func (a PrimaryKeyTable) Create(ctx HasKVStore, obj PrimaryKeyed) error { + rowID := PrimaryKey(obj) + if a.table.Has(ctx, rowID) { + return ErrUniqueConstraint + } + return a.table.Create(ctx, rowID, obj) +} + +// Save updates the given object under the primary key. It expects the key to exists already +// and fails with an `ErrNotFound` otherwise. Any caller must therefore make sure that this contract +// is fulfilled. Parameters must not be nil. +// +// Save iterates though the registered callbacks and may add or remove secondary index keys by them. +func (a PrimaryKeyTable) Save(ctx HasKVStore, newValue PrimaryKeyed) error { + return a.table.Save(ctx, PrimaryKey(newValue), newValue) +} + +// Delete removes the object. It expects the primary key to exists already +// and fails with a `ErrNotFound` otherwise. Any caller must therefore make sure that this contract +// is fulfilled. +// +// Delete iterates though the registered callbacks and removes secondary index keys by them. +func (a PrimaryKeyTable) Delete(ctx HasKVStore, obj PrimaryKeyed) error { + return a.table.Delete(ctx, PrimaryKey(obj)) +} + +// Has checks if a key exists. Panics on nil key. +func (a PrimaryKeyTable) Has(ctx HasKVStore, primaryKey RowID) bool { + return a.table.Has(ctx, primaryKey) +} + +// Contains returns true when an object with same type and primary key is persisted in this table. +func (a PrimaryKeyTable) Contains(ctx HasKVStore, obj PrimaryKeyed) bool { + if err := assertCorrectType(a.table.model, obj); err != nil { + return false + } + return a.table.Has(ctx, PrimaryKey(obj)) +} + +// GetOne load the object persisted for the given primary Key into the dest parameter. +// If none exists `ErrNotFound` is returned instead. Parameters must not be nil. +func (a PrimaryKeyTable) GetOne(ctx HasKVStore, primKey RowID, dest codec.ProtoMarshaler) error { + return a.table.GetOne(ctx, primKey, dest) +} + +// PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. +// Example: +// it, err := idx.PrefixScan(ctx, start, end) +// if err !=nil { +// return err +// } +// const defaultLimit = 20 +// it = LimitIterator(it, defaultLimit) +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (a PrimaryKeyTable) PrefixScan(ctx HasKVStore, start, end []byte) (Iterator, error) { + return a.table.PrefixScan(ctx, start, end) +} + +// ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. See `LimitIterator` +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (a PrimaryKeyTable) ReversePrefixScan(ctx HasKVStore, start, end []byte) (Iterator, error) { + return a.table.ReversePrefixScan(ctx, start, end) +} + +// Table satisfies the TableExportable interface and must not be used otherwise. +func (a PrimaryKeyTable) Table() table { + return a.table +} diff --git a/regen/orm/primary_key_property_test.go b/regen/orm/primary_key_property_test.go new file mode 100644 index 0000000000..663967d324 --- /dev/null +++ b/regen/orm/primary_key_property_test.go @@ -0,0 +1,200 @@ +package orm_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "pgregory.net/rapid" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestPrimaryKeyTable(t *testing.T) { + rapid.Check(t, rapid.Run(&primaryKeyMachine{})) +} + +// primaryKeyMachine is a state machine model of the PrimaryKeyTable. The state +// is modelled as a map of strings to GroupMembers. +type primaryKeyMachine struct { + ctx orm.HasKVStore + table *orm.PrimaryKeyTable + state map[string]*testdata.GroupMember +} + +// stateKeys gets all the keys in the model map +func (m *primaryKeyMachine) stateKeys() []string { + keys := make([]string, len(m.state)) + + i := 0 + for k := range m.state { + keys[i] = k + i++ + } + + return keys +} + +// Generate a GroupMember that has a 50% chance of being a part of the existing +// state +func (m *primaryKeyMachine) genGroupMember() *rapid.Generator { + genStateGroupMember := rapid.Custom(func(t *rapid.T) *testdata.GroupMember { + pk := rapid.SampledFrom(m.stateKeys()).Draw(t, "key").(string) + return m.state[pk] + }) + + if len(m.stateKeys()) == 0 { + return genGroupMember + } else { + return rapid.OneOf(genGroupMember, genStateGroupMember) + } +} + +// Init creates a new instance of the state machine model by building the real +// table and making the empty model map +func (m *primaryKeyMachine) Init(t *rapid.T) { + // Create context + m.ctx = orm.NewMockContext() + + // Create primary key table + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + storeKey := sdk.NewKVStoreKey("test") + const testTablePrefix = iota + table := orm.NewPrimaryKeyTableBuilder( + testTablePrefix, + storeKey, + &testdata.GroupMember{}, + orm.Max255DynamicLengthIndexKeyCodec{}, + cdc, + ).Build() + + m.table = &table + + // Create model state + m.state = make(map[string]*testdata.GroupMember) +} + +// Check that the real values match the state values. This is kind of overkill, +// because we should catch any discrepancies in a Has command. +func (m *primaryKeyMachine) Check(t *rapid.T) { + iter, err := m.table.PrefixScan(m.ctx, nil, nil) + require.NoError(t, err) + + for { + var dest testdata.GroupMember + rowID, err := iter.LoadNext(&dest) + if err == orm.ErrIteratorDone { + break + } else { + require.Equal(t, *m.state[string(rowID)], dest) + } + } +} + +// Create is one of the model commands. It adds an object to the table, creating +// an error if it already exists. +func (m *primaryKeyMachine) Create(t *rapid.T) { + g := genGroupMember.Draw(t, "g").(*testdata.GroupMember) + pk := string(orm.PrimaryKey(g)) + + t.Logf("pk: %v", pk) + t.Logf("m.state: %v", m.state) + + err := m.table.Create(m.ctx, g) + + if m.state[pk] != nil { + require.Error(t, err) + } else { + require.NoError(t, err) + m.state[pk] = g + } +} + +// Save is one of the model commands. It updates the value at a given primary +// key and fails if that primary key doesn't already exist in the table. +func (m *primaryKeyMachine) Save(t *rapid.T) { + gm := m.genGroupMember().Draw(t, "gm").(*testdata.GroupMember) + + // We can only really change the weight here, because Group and Member + // both form part of the PrimaryKey + newWeight := rapid.Uint64().Draw(t, "newWeight").(uint64) + gm.Weight = newWeight + + // Perform the real Save + err := m.table.Save(m.ctx, gm) + + if m.state[string(orm.PrimaryKey(gm))] == nil { + // If there's no value in the model, we expect an error + require.Error(t, err) + } else { + // If we have a value in the model, expect no error + require.NoError(t, err) + + // Update the model with the new value + m.state[string(orm.PrimaryKey(gm))] = gm + } +} + +// Delete is one of the model commands. It removes the object with the given +// primary key from the table and returns an error if that primary key doesn't +// already exist in the table. +func (m *primaryKeyMachine) Delete(t *rapid.T) { + gm := m.genGroupMember().Draw(t, "gm").(*testdata.GroupMember) + + // Perform the real Delete + err := m.table.Delete(m.ctx, gm) + + if m.state[string(orm.PrimaryKey(gm))] == nil { + // If there's no value in the model, we expect an error + require.Error(t, err) + } else { + // If we have a value in the model, expect no error + require.NoError(t, err) + + // Delete the value from the model + delete(m.state, string(orm.PrimaryKey(gm))) + } +} + +// Has is one of the model commands. It checks whether a key already exists in +// the table. +func (m *primaryKeyMachine) Has(t *rapid.T) { + pk := orm.PrimaryKey(m.genGroupMember().Draw(t, "g").(*testdata.GroupMember)) + + realHas := m.table.Has(m.ctx, pk) + modelHas := m.state[string(pk)] != nil + + require.Equal(t, realHas, modelHas) +} + +// GetOne is one of the model commands. It fetches an object from the table by +// its primary key and returns an error if that primary key isn't in the table. +func (m *primaryKeyMachine) GetOne(t *rapid.T) { + pk := orm.PrimaryKey(m.genGroupMember().Draw(t, "gm").(*testdata.GroupMember)) + + var gm testdata.GroupMember + + err := m.table.GetOne(m.ctx, pk, &gm) + t.Logf("gm: %v", gm) + + if m.state[string(pk)] == nil { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, *m.state[string(pk)], gm) + } +} + +// genGroupMember generates a new group member. At the moment it doesn't +// generate empty strings for Group or Member. +var genGroupMember = rapid.Custom(func(t *rapid.T) *testdata.GroupMember { + return &testdata.GroupMember{ + Group: []byte(rapid.StringN(1, 100, 150).Draw(t, "group").(string)), + Member: []byte(rapid.StringN(1, 100, 150).Draw(t, "member").(string)), + Weight: rapid.Uint64().Draw(t, "weight").(uint64), + } +}) diff --git a/regen/orm/primary_key_test.go b/regen/orm/primary_key_test.go new file mode 100644 index 0000000000..3673b4ec25 --- /dev/null +++ b/regen/orm/primary_key_test.go @@ -0,0 +1,337 @@ +package orm_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestPrimaryKeyTablePrefixScan(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const ( + testTablePrefix = iota + ) + + tb := orm.NewPrimaryKeyTableBuilder(testTablePrefix, storeKey, &testdata.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc). + Build() + + ctx := orm.NewMockContext() + + const anyWeight = 1 + m1 := testdata.GroupMember{ + Group: []byte("group-a"), + Member: []byte("member-one"), + Weight: anyWeight, + } + m2 := testdata.GroupMember{ + Group: []byte("group-a"), + Member: []byte("member-two"), + Weight: anyWeight, + } + m3 := testdata.GroupMember{ + Group: []byte("group-b"), + Member: []byte("member-two"), + Weight: anyWeight, + } + for _, g := range []testdata.GroupMember{m1, m2, m3} { + require.NoError(t, tb.Create(ctx, &g)) + } + + specs := map[string]struct { + start, end []byte + expResult []testdata.GroupMember + expRowIDs []orm.RowID + expError *errors.Error + method func(ctx orm.HasKVStore, start, end []byte) (orm.Iterator, error) + }{ + "exact match with a single result": { + start: append( + orm.AddLengthPrefix([]byte("group-a")), + orm.AddLengthPrefix([]byte("member-one"))..., + ), // == orm.PrimaryKey(&m1) + end: append( + orm.AddLengthPrefix([]byte("group-a")), + orm.AddLengthPrefix([]byte("member-two"))..., + ), // == orm.PrimaryKey(&m2) + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1)}, + }, + "one result by prefix": { + start: orm.AddLengthPrefix([]byte("group-a")), + end: append( + orm.AddLengthPrefix([]byte("group-a")), + orm.AddLengthPrefix([]byte("member-two"))..., + ), // == orm.PrimaryKey(&m2) + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1)}, + }, + "multi key elements by group prefix": { + start: orm.AddLengthPrefix([]byte("group-a")), + end: orm.AddLengthPrefix([]byte("group-b")), + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1, m2}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1), orm.PrimaryKey(&m2)}, + }, + "open end query with second group": { + start: orm.AddLengthPrefix([]byte("group-b")), + end: nil, + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m3}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m3)}, + }, + "open end query with all": { + start: orm.AddLengthPrefix([]byte("group-a")), + end: nil, + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1, m2, m3}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1), orm.PrimaryKey(&m2), orm.PrimaryKey(&m3)}, + }, + "open start query": { + start: nil, + end: orm.AddLengthPrefix([]byte("group-b")), + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1, m2}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1), orm.PrimaryKey(&m2)}, + }, + "open start and end query": { + start: nil, + end: nil, + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1, m2, m3}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1), orm.PrimaryKey(&m2), orm.PrimaryKey(&m3)}, + }, + "all matching prefix": { + start: orm.AddLengthPrefix([]byte("group")), // == LengthPrefix + "group" + end: nil, + method: tb.PrefixScan, + expResult: []testdata.GroupMember{m1, m2, m3}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1), orm.PrimaryKey(&m2), orm.PrimaryKey(&m3)}, + }, + "non matching prefix": { + start: []byte("nobody"), + end: nil, + method: tb.PrefixScan, + expResult: []testdata.GroupMember{}, + }, + "start equals end": { + start: []byte("any"), + end: []byte("any"), + method: tb.PrefixScan, + expError: orm.ErrArgument, + }, + "start after end": { + start: []byte("b"), + end: []byte("a"), + method: tb.PrefixScan, + expError: orm.ErrArgument, + }, + "reverse: exact match with a single result": { + start: append( + orm.AddLengthPrefix([]byte("group-a")), + orm.AddLengthPrefix([]byte("member-one"))..., + ), // == orm.PrimaryKey(&m1) + end: append( + orm.AddLengthPrefix([]byte("group-a")), + orm.AddLengthPrefix([]byte("member-two"))..., + ), // == orm.PrimaryKey(&m2) + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1)}, + }, + "reverse: one result by prefix": { + start: orm.AddLengthPrefix([]byte("group-a")), + end: append( + orm.AddLengthPrefix([]byte("group-a")), + orm.AddLengthPrefix([]byte("member-two"))..., + ), // == orm.PrimaryKey(&m2) + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m1)}, + }, + "reverse: multi key elements by group prefix": { + start: orm.AddLengthPrefix([]byte("group-a")), + end: orm.AddLengthPrefix([]byte("group-b")), + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m2, m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m2), orm.PrimaryKey(&m1)}, + }, + "reverse: open end query with second group": { + start: orm.AddLengthPrefix([]byte("group-b")), + end: nil, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m3}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m3)}, + }, + "reverse: open end query with all": { + start: orm.AddLengthPrefix([]byte("group-a")), + end: nil, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m3, m2, m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m3), orm.PrimaryKey(&m2), orm.PrimaryKey(&m1)}, + }, + "reverse: open start query": { + start: nil, + end: orm.AddLengthPrefix([]byte("group-b")), + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m2, m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m2), orm.PrimaryKey(&m1)}, + }, + "reverse: open start and end query": { + start: nil, + end: nil, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m3, m2, m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m3), orm.PrimaryKey(&m2), orm.PrimaryKey(&m1)}, + }, + "reverse: all matching prefix": { + start: orm.AddLengthPrefix([]byte("group")), // == LengthPrefix + "group" + end: nil, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{m3, m2, m1}, + expRowIDs: []orm.RowID{orm.PrimaryKey(&m3), orm.PrimaryKey(&m2), orm.PrimaryKey(&m1)}, + }, + "reverse: non matching prefix": { + start: []byte("nobody"), + end: nil, + method: tb.ReversePrefixScan, + expResult: []testdata.GroupMember{}, + }, + "reverse: start equals end": { + start: []byte("any"), + end: []byte("any"), + method: tb.ReversePrefixScan, + expError: orm.ErrArgument, + }, + "reverse: start after end": { + start: []byte("b"), + end: []byte("a"), + method: tb.ReversePrefixScan, + expError: orm.ErrArgument, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + it, err := spec.method(ctx, spec.start, spec.end) + require.True(t, spec.expError.Is(err), "expected #+v but got #+v", spec.expError, err) + if spec.expError != nil { + return + } + var loaded []testdata.GroupMember + rowIDs, err := orm.ReadAll(it, &loaded) + require.NoError(t, err) + assert.Equal(t, spec.expResult, loaded) + assert.Equal(t, spec.expRowIDs, rowIDs) + }) + } +} + +func TestContains(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const testTablePrefix = iota + + tb := orm.NewPrimaryKeyTableBuilder(testTablePrefix, storeKey, &testdata.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc). + Build() + + ctx := orm.NewMockContext() + + myPersistentObj := testdata.GroupMember{ + Group: []byte("group-a"), + Member: []byte("member-one"), + Weight: 1, + } + err := tb.Create(ctx, &myPersistentObj) + require.NoError(t, err) + + specs := map[string]struct { + src orm.PrimaryKeyed + exp bool + }{ + + "same object": {src: &myPersistentObj, exp: true}, + "clone": { + src: &testdata.GroupMember{ + Group: []byte("group-a"), + Member: []byte("member-one"), + Weight: 1, + }, + exp: true, + }, + "different primary key": { + src: &testdata.GroupMember{ + Group: []byte("another group"), + Member: []byte("member-one"), + Weight: 1, + }, + exp: false, + }, + "different type, same key": { + src: mockPrimaryKeyed{&myPersistentObj}, + exp: false, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + got := tb.Contains(ctx, spec.src) + assert.Equal(t, spec.exp, got) + }) + } +} + +func TestAddLengthPrefix(t *testing.T) { + tcs := []struct { + name string + in []byte + expected []byte + }{ + {"empty", []byte{}, []byte{0}}, + {"nil", nil, []byte{0}}, + {"some data", []byte{0, 1, 100, 200}, []byte{4, 0, 1, 100, 200}}, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + out := orm.AddLengthPrefix(tc.in) + require.Equal(t, tc.expected, out) + }) + } + + require.Panics(t, func() { + orm.AddLengthPrefix(make([]byte, 300)) + }) +} + +func TestNullTerminatedBytes(t *testing.T) { + tcs := []struct { + name string + in string + expected []byte + }{ + {"empty", "", []byte{0}}, + {"some data", "abc", []byte{0x61, 0x62, 0x63, 0}}, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + out := orm.NullTerminatedBytes(tc.in) + require.Equal(t, tc.expected, out) + }) + } +} + +type mockPrimaryKeyed struct { + *testdata.GroupMember +} diff --git a/regen/orm/sequence.go b/regen/orm/sequence.go new file mode 100644 index 0000000000..11b1b186c7 --- /dev/null +++ b/regen/orm/sequence.go @@ -0,0 +1,83 @@ +package orm + +import ( + "encoding/binary" + + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// sequenceStorageKey is a fix key to read/ write data on the storage layer +var sequenceStorageKey = []byte{0x1} + +// sequence is a persistent unique key generator based on a counter. +type Sequence struct { + storeKey sdk.StoreKey + prefix byte +} + +func NewSequence(storeKey sdk.StoreKey, prefix byte) Sequence { + return Sequence{ + prefix: prefix, + storeKey: storeKey, + } +} + +// NextVal increments and persists the counter by one and returns the value. +func (s Sequence) NextVal(ctx HasKVStore) uint64 { + store := prefix.NewStore(ctx.KVStore(s.storeKey), []byte{s.prefix}) + v := store.Get(sequenceStorageKey) + seq := DecodeSequence(v) + seq++ + store.Set(sequenceStorageKey, EncodeSequence(seq)) + return seq +} + +// CurVal returns the last value used. 0 if none. +func (s Sequence) CurVal(ctx HasKVStore) uint64 { + store := prefix.NewStore(ctx.KVStore(s.storeKey), []byte{s.prefix}) + v := store.Get(sequenceStorageKey) + return DecodeSequence(v) +} + +// PeekNextVal returns the CurVal + increment step. Not persistent. +func (s Sequence) PeekNextVal(ctx HasKVStore) uint64 { + store := prefix.NewStore(ctx.KVStore(s.storeKey), []byte{s.prefix}) + v := store.Get(sequenceStorageKey) + return DecodeSequence(v) + 1 +} + +// InitVal sets the start value for the sequence. It must be called only once on an empty DB. +// Otherwise an error is returned when the key exists. The given start value is stored as current +// value. +// +// It is recommended to call this method only for a sequence start value other than `1` as the +// method consumes unnecessary gas otherwise. A scenario would be an import from genesis. +func (s Sequence) InitVal(ctx HasKVStore, seq uint64) error { + store := prefix.NewStore(ctx.KVStore(s.storeKey), []byte{s.prefix}) + if store.Has(sequenceStorageKey) { + return errors.Wrap(ErrUniqueConstraint, "already initialized") + } + store.Set(sequenceStorageKey, EncodeSequence(seq)) + return nil +} + +// DecodeSequence converts the binary representation into an Uint64 value. +func DecodeSequence(bz []byte) uint64 { + if bz == nil { + return 0 + } + val := binary.BigEndian.Uint64(bz) + return val +} + +// EncodedSeqLength number of bytes used for the binary representation of a sequence value. +const EncodedSeqLength = 8 + +// EncodeSequence converts the sequence value into the binary representation. +func EncodeSequence(val uint64) []byte { + bz := make([]byte, EncodedSeqLength) + binary.BigEndian.PutUint64(bz, val) + return bz +} diff --git a/regen/orm/sequence_property_test.go b/regen/orm/sequence_property_test.go new file mode 100644 index 0000000000..459551f250 --- /dev/null +++ b/regen/orm/sequence_property_test.go @@ -0,0 +1,70 @@ +package orm_test + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + "pgregory.net/rapid" + + "github.com/cosmos/cosmos-sdk/regen/orm" +) + +func TestSequence(t *testing.T) { + rapid.Check(t, rapid.Run(&sequenceMachine{})) +} + +// sequenceMachine is a state machine model of Sequence. It simply uses a uint64 +// as the model of the sequence. +type sequenceMachine struct { + ctx orm.HasKVStore + seq *orm.Sequence + state uint64 +} + +// Init sets up the real Sequence, including choosing a random initial value, +// and intialises the model state +func (m *sequenceMachine) Init(t *rapid.T) { + // Create context + m.ctx = orm.NewMockContext() + + // Create primary key table + storeKey := sdk.NewKVStoreKey("test") + seq := orm.NewSequence(storeKey, 0x1) + m.seq = &seq + + // Choose initial sequence value + initSeqVal := rapid.Uint64().Draw(t, "initSeqVal").(uint64) + err := m.seq.InitVal(m.ctx, initSeqVal) + require.NoError(t, err) + + // Create model state + m.state = initSeqVal +} + +// Check does nothing, because all our invariants are captured in the commands +func (m *sequenceMachine) Check(t *rapid.T) {} + +// NextVal is one of the model commands. It checks that the next value of the +// sequence matches the model and increments the model state. +func (m *sequenceMachine) NextVal(t *rapid.T) { + // Check that the next value in the sequence matches the model + require.Equal(t, m.state+1, m.seq.NextVal(m.ctx)) + + // Increment the model state + m.state++ +} + +// CurVal is one of the model commands. It checks that the current value of the +// sequence matches the model. +func (m *sequenceMachine) CurVal(t *rapid.T) { + // Check the the current value matches the model + require.Equal(t, m.state, m.seq.CurVal(m.ctx)) +} + +// PeekNextVal is one of the model commands. It checks that the next value of +// the sequence matches the model without modifying the state. +func (m *sequenceMachine) PeekNextVal(t *rapid.T) { + // Check that the next value in the sequence matches the model + require.Equal(t, m.state+1, m.seq.PeekNextVal(m.ctx)) +} diff --git a/regen/orm/sequence_test.go b/regen/orm/sequence_test.go new file mode 100644 index 0000000000..6addc09055 --- /dev/null +++ b/regen/orm/sequence_test.go @@ -0,0 +1,24 @@ +package orm + +import ( + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/assert" +) + +func TestSequenceIncrements(t *testing.T) { + storeKey := sdk.NewKVStoreKey("test") + ctx := NewMockContext() + + seq := NewSequence(storeKey, 0x1) + var i uint64 + for i = 1; i < 10; i++ { + autoID := seq.NextVal(ctx) + assert.Equal(t, i, autoID) + assert.Equal(t, i, seq.CurVal(ctx)) + } + // and persisted + seq = NewSequence(storeKey, 0x1) + assert.Equal(t, uint64(9), seq.CurVal(ctx)) +} diff --git a/regen/orm/table.go b/regen/orm/table.go new file mode 100644 index 0000000000..8708492bd1 --- /dev/null +++ b/regen/orm/table.go @@ -0,0 +1,303 @@ +package orm + +import ( + "bytes" + "reflect" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/store/prefix" + "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +var _ Indexable = &tableBuilder{} + +type tableBuilder struct { + model reflect.Type + prefixData byte + storeKey sdk.StoreKey + indexKeyCodec IndexKeyCodec + afterSave []AfterSaveInterceptor + afterDelete []AfterDeleteInterceptor + cdc codec.Codec +} + +// newTableBuilder creates a builder to setup a table object. +func newTableBuilder(prefixData byte, storeKey sdk.StoreKey, model codec.ProtoMarshaler, idxKeyCodec IndexKeyCodec, cdc codec.Codec) *tableBuilder { + if model == nil { + panic("Model must not be nil") + } + if storeKey == nil { + panic("StoreKey must not be nil") + } + if idxKeyCodec == nil { + panic("IndexKeyCodec must not be nil") + } + tp := reflect.TypeOf(model) + if tp.Kind() == reflect.Ptr { + tp = tp.Elem() + } + return &tableBuilder{ + prefixData: prefixData, + storeKey: storeKey, + model: tp, + indexKeyCodec: idxKeyCodec, + cdc: cdc, + } +} + +// TestTableBuilder exposes the private tableBuilder type for testing purposes. +// It is not safe to use this outside of test code. +func TestTableBuilder(prefixData byte, storeKey sdk.StoreKey, model codec.ProtoMarshaler, idxKeyCodec IndexKeyCodec, cdc codec.Codec) *tableBuilder { + return newTableBuilder(prefixData, storeKey, model, idxKeyCodec, cdc) +} + +func (a tableBuilder) IndexKeyCodec() IndexKeyCodec { + return a.indexKeyCodec +} + +// RowGetter returns a type safe RowGetter. +func (a tableBuilder) RowGetter() RowGetter { + return NewTypeSafeRowGetter(a.storeKey, a.prefixData, a.model, a.cdc) +} + +func (a tableBuilder) StoreKey() sdk.StoreKey { + return a.storeKey +} + +// Build creates a new table object. +func (a tableBuilder) Build() table { + return table{ + model: a.model, + prefix: a.prefixData, + storeKey: a.storeKey, + afterSave: a.afterSave, + afterDelete: a.afterDelete, + cdc: a.cdc, + } +} + +// AddAfterSaveInterceptor can be used to register a callback function that is executed after an object is created and/or updated. +func (a *tableBuilder) AddAfterSaveInterceptor(interceptor AfterSaveInterceptor) { + a.afterSave = append(a.afterSave, interceptor) +} + +// AddAfterDeleteInterceptor can be used to register a callback function that is executed after an object is deleted. +func (a *tableBuilder) AddAfterDeleteInterceptor(interceptor AfterDeleteInterceptor) { + a.afterDelete = append(a.afterDelete, interceptor) +} + +var _ TableExportable = &table{} + +// table is the high level object to storage mapper functionality. Persistent +// entities are stored by an unique identifier called `RowID`. The table struct +// does not: +// - enforce uniqueness of the `RowID` +// - enforce prefix uniqueness of keys, i.e. not allowing one key to be a prefix +// of another +// - optimize Gas usage conditions +// The caller must ensure that these things are handled. The table struct is +// private, so that we only custom tables built on top of table, that do satisfy +// these requirements. +type table struct { + model reflect.Type + prefix byte + storeKey sdk.StoreKey + afterSave []AfterSaveInterceptor + afterDelete []AfterDeleteInterceptor + cdc codec.Codec +} + +// Create persists the given object under the rowID key. It does not check if the +// key already exists. Any caller must either make sure that this contract is fulfilled +// by providing a universal unique ID or sequence that is guaranteed to not exist yet or +// by checking the state via `Has` function before. +// +// Create iterates though the registered callbacks and may add secondary index keys by them. +func (a table) Create(ctx HasKVStore, rowID RowID, obj codec.ProtoMarshaler) error { + if len(rowID) == 0 { + return ErrEmptyKey + } + if err := assertCorrectType(a.model, obj); err != nil { + return err + } + if err := assertValid(obj); err != nil { + return err + } + store := prefix.NewStore(ctx.KVStore(a.storeKey), []byte{a.prefix}) + v, err := a.cdc.Marshal(obj) + if err != nil { + return errors.Wrapf(err, "failed to serialize %T", obj) + } + store.Set(rowID, v) + for i, itc := range a.afterSave { + if err := itc(ctx, rowID, obj, nil); err != nil { + return errors.Wrapf(err, "interceptor %d failed", i) + } + } + return nil +} + +// Save updates the given object under the rowID key. It expects the key to exists already +// and fails with an `ErrNotFound` otherwise. Any caller must therefore make sure that this contract +// is fulfilled. Parameters must not be nil. +// +// Save iterates though the registered callbacks and may add or remove secondary index keys by them. +func (a table) Save(ctx HasKVStore, rowID RowID, newValue codec.ProtoMarshaler) error { + if err := assertCorrectType(a.model, newValue); err != nil { + return err + } + if err := assertValid(newValue); err != nil { + return err + } + + store := prefix.NewStore(ctx.KVStore(a.storeKey), []byte{a.prefix}) + var oldValue = reflect.New(a.model).Interface().(codec.ProtoMarshaler) + + if err := a.GetOne(ctx, rowID, oldValue); err != nil { + return errors.Wrap(err, "load old value") + } + newValueEncoded, err := a.cdc.Marshal(newValue) + if err != nil { + return errors.Wrapf(err, "failed to serialize %T", newValue) + } + + store.Set(rowID, newValueEncoded) + for i, itc := range a.afterSave { + if err := itc(ctx, rowID, newValue, oldValue); err != nil { + return errors.Wrapf(err, "interceptor %d failed", i) + } + } + return nil +} + +func assertValid(obj codec.ProtoMarshaler) error { + if v, ok := obj.(Validateable); ok { + if err := v.ValidateBasic(); err != nil { + return err + } + } + return nil +} + +// Delete removes the object under the rowID key. It expects the key to exists already +// and fails with a `ErrNotFound` otherwise. Any caller must therefore make sure that this contract +// is fulfilled. +// +// Delete iterates though the registered callbacks and removes secondary index keys by them. +func (a table) Delete(ctx HasKVStore, rowID RowID) error { + store := prefix.NewStore(ctx.KVStore(a.storeKey), []byte{a.prefix}) + + var oldValue = reflect.New(a.model).Interface().(codec.ProtoMarshaler) + if err := a.GetOne(ctx, rowID, oldValue); err != nil { + return errors.Wrap(err, "load old value") + } + store.Delete(rowID) + + for i, itc := range a.afterDelete { + if err := itc(ctx, rowID, oldValue); err != nil { + return errors.Wrapf(err, "delete interceptor %d failed", i) + } + } + return nil +} + +// Has checks if a key exists. Panics on nil key, and returns false on empty key. +func (a table) Has(ctx HasKVStore, key RowID) bool { + // We don't allow creation of values with an empty key, so Has will + // always return false + if len(key) == 0 { + return false + } + store := prefix.NewStore(ctx.KVStore(a.storeKey), []byte{a.prefix}) + it := store.Iterator(PrefixRange(key)) + defer it.Close() + return it.Valid() +} + +// GetOne load the object persisted for the given RowID into the dest parameter. +// If none exists `ErrNotFound` is returned instead. Parameters must not be nil. +func (a table) GetOne(ctx HasKVStore, rowID RowID, dest codec.ProtoMarshaler) error { + // We don't allow creation of values with an empty key, so we always + // return not found error + if len(rowID) == 0 { + return ErrNotFound + } + x := NewTypeSafeRowGetter(a.storeKey, a.prefix, a.model, a.cdc) + return x(ctx, rowID, dest) +} + +// PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. +// Example: +// it, err := idx.PrefixScan(ctx, start, end) +// if err !=nil { +// return err +// } +// const defaultLimit = 20 +// it = LimitIterator(it, defaultLimit) +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (a table) PrefixScan(ctx HasKVStore, start, end RowID) (Iterator, error) { + if start != nil && end != nil && bytes.Compare(start, end) >= 0 { + return NewInvalidIterator(), errors.Wrap(ErrArgument, "start must be before end") + } + store := prefix.NewStore(ctx.KVStore(a.storeKey), []byte{a.prefix}) + return &typeSafeIterator{ + ctx: ctx, + rowGetter: NewTypeSafeRowGetter(a.storeKey, a.prefix, a.model, a.cdc), + it: store.Iterator(start, end), + }, nil +} + +// ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. See `LimitIterator` +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (a table) ReversePrefixScan(ctx HasKVStore, start, end RowID) (Iterator, error) { + if start != nil && end != nil && bytes.Compare(start, end) >= 0 { + return NewInvalidIterator(), errors.Wrap(ErrArgument, "start must be before end") + } + store := prefix.NewStore(ctx.KVStore(a.storeKey), []byte{a.prefix}) + return &typeSafeIterator{ + ctx: ctx, + rowGetter: NewTypeSafeRowGetter(a.storeKey, a.prefix, a.model, a.cdc), + it: store.ReverseIterator(start, end), + }, nil +} + +func (a table) Table() table { + return a +} + +// typeSafeIterator is initialized with a type safe RowGetter only. +type typeSafeIterator struct { + ctx HasKVStore + rowGetter RowGetter + it types.Iterator +} + +func (i typeSafeIterator) LoadNext(dest codec.ProtoMarshaler) (RowID, error) { + if !i.it.Valid() { + return nil, ErrIteratorDone + } + rowID := i.it.Key() + i.it.Next() + return rowID, i.rowGetter(i.ctx, rowID, dest) +} + +func (i typeSafeIterator) Close() error { + i.it.Close() + return nil +} diff --git a/regen/orm/table_test.go b/regen/orm/table_test.go new file mode 100644 index 0000000000..26525f8bd5 --- /dev/null +++ b/regen/orm/table_test.go @@ -0,0 +1,129 @@ +package orm_test + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestCreate(t *testing.T) { + specs := map[string]struct { + src codec.ProtoMarshaler + expErr *errors.Error + }{ + "happy path": { + src: &testdata.GroupInfo{ + Description: "my group", + Admin: sdk.AccAddress([]byte("my-admin-address")), + }, + }, + "wrong type": { + src: &testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("member-address")), + Weight: 10, + }, + expErr: orm.ErrType, + }, + "model validation fails": { + src: &testdata.GroupInfo{Description: "invalid"}, + expErr: testdata.ErrTest, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const anyPrefix = 0x10 + tableBuilder := orm.TestTableBuilder(anyPrefix, storeKey, &testdata.GroupInfo{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + myTable := tableBuilder.Build() + + ctx := orm.NewMockContext() + err := myTable.Create(ctx, []byte("my-id"), spec.src) + + require.True(t, spec.expErr.Is(err), err) + shouldExists := spec.expErr == nil + assert.Equal(t, shouldExists, myTable.Has(ctx, []byte("my-id")), fmt.Sprintf("expected %v", shouldExists)) + + // then + var loaded testdata.GroupInfo + err = myTable.GetOne(ctx, []byte("my-id"), &loaded) + if spec.expErr != nil { + require.True(t, orm.ErrNotFound.Is(err)) + return + } + require.NoError(t, err) + assert.Equal(t, spec.src, &loaded) + }) + } + +} +func TestUpdate(t *testing.T) { + specs := map[string]struct { + src codec.ProtoMarshaler + expErr *errors.Error + }{ + "happy path": { + src: &testdata.GroupInfo{ + Description: "my group", + Admin: sdk.AccAddress([]byte("my-admin-address")), + }, + }, + "wrong type": { + src: &testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("member-address")), + Weight: 9999, + }, + expErr: orm.ErrType, + }, + "model validation fails": { + src: &testdata.GroupInfo{Description: "invalid"}, + expErr: testdata.ErrTest, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + const anyPrefix = 0x10 + tableBuilder := orm.TestTableBuilder(anyPrefix, storeKey, &testdata.GroupInfo{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + myTable := tableBuilder.Build() + + initValue := testdata.GroupInfo{ + Description: "my old group description", + Admin: sdk.AccAddress([]byte("my-old-admin-address")), + } + ctx := orm.NewMockContext() + err := myTable.Create(ctx, []byte("my-id"), &initValue) + require.NoError(t, err) + + // when + err = myTable.Save(ctx, []byte("my-id"), spec.src) + require.True(t, spec.expErr.Is(err), "got ", err) + + // then + var loaded testdata.GroupInfo + require.NoError(t, myTable.GetOne(ctx, []byte("my-id"), &loaded)) + if spec.expErr == nil { + assert.Equal(t, spec.src, &loaded) + } else { + assert.Equal(t, initValue, loaded) + } + }) + } + +} diff --git a/regen/orm/testdata/codec.pb.go b/regen/orm/testdata/codec.pb.go new file mode 100644 index 0000000000..237ff71592 --- /dev/null +++ b/regen/orm/testdata/codec.pb.go @@ -0,0 +1,679 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: codec.proto + +package testdata + +import ( + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type GroupInfo struct { + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Admin github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,3,opt,name=admin,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"admin,omitempty"` +} + +func (m *GroupInfo) Reset() { *m = GroupInfo{} } +func (m *GroupInfo) String() string { return proto.CompactTextString(m) } +func (*GroupInfo) ProtoMessage() {} +func (*GroupInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_9610d574777ab505, []int{0} +} +func (m *GroupInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GroupInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GroupInfo.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 *GroupInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_GroupInfo.Merge(m, src) +} +func (m *GroupInfo) XXX_Size() int { + return m.Size() +} +func (m *GroupInfo) XXX_DiscardUnknown() { + xxx_messageInfo_GroupInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_GroupInfo proto.InternalMessageInfo + +func (m *GroupInfo) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *GroupInfo) GetDescription() string { + if m != nil { + return m.Description + } + return "" +} + +func (m *GroupInfo) GetAdmin() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Admin + } + return nil +} + +type GroupMember struct { + Group github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,opt,name=group,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"group,omitempty"` + Member github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,2,opt,name=member,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"member,omitempty"` + Weight uint64 `protobuf:"varint,3,opt,name=weight,proto3" json:"weight,omitempty"` +} + +func (m *GroupMember) Reset() { *m = GroupMember{} } +func (m *GroupMember) String() string { return proto.CompactTextString(m) } +func (*GroupMember) ProtoMessage() {} +func (*GroupMember) Descriptor() ([]byte, []int) { + return fileDescriptor_9610d574777ab505, []int{1} +} +func (m *GroupMember) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GroupMember) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GroupMember.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 *GroupMember) XXX_Merge(src proto.Message) { + xxx_messageInfo_GroupMember.Merge(m, src) +} +func (m *GroupMember) XXX_Size() int { + return m.Size() +} +func (m *GroupMember) XXX_DiscardUnknown() { + xxx_messageInfo_GroupMember.DiscardUnknown(m) +} + +var xxx_messageInfo_GroupMember proto.InternalMessageInfo + +func (m *GroupMember) GetGroup() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Group + } + return nil +} + +func (m *GroupMember) GetMember() github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Member + } + return nil +} + +func (m *GroupMember) GetWeight() uint64 { + if m != nil { + return m.Weight + } + return 0 +} + +func init() { + proto.RegisterType((*GroupInfo)(nil), "testdata.GroupInfo") + proto.RegisterType((*GroupMember)(nil), "testdata.GroupMember") +} + +func init() { proto.RegisterFile("codec.proto", fileDescriptor_9610d574777ab505) } + +var fileDescriptor_9610d574777ab505 = []byte{ + // 296 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x91, 0xb1, 0x4e, 0xc3, 0x30, + 0x10, 0x86, 0x6b, 0x28, 0xa5, 0x75, 0x99, 0x2c, 0x84, 0x0a, 0x83, 0x89, 0x3a, 0x75, 0x69, 0x23, + 0xe0, 0x09, 0xda, 0xa5, 0xaa, 0x04, 0x4b, 0x46, 0x16, 0x94, 0xd8, 0x87, 0x6b, 0x15, 0xe7, 0x22, + 0xdb, 0x55, 0xc5, 0x5b, 0xc0, 0xe3, 0xf0, 0x06, 0x8c, 0x1d, 0x99, 0x10, 0x4a, 0xde, 0x82, 0x09, + 0xc5, 0x0d, 0x52, 0xe7, 0x4e, 0xf6, 0x7f, 0xd6, 0x7d, 0xfe, 0x4e, 0x47, 0xfb, 0x02, 0x25, 0x88, + 0x49, 0x61, 0xd1, 0x23, 0xeb, 0x7a, 0x70, 0x5e, 0xa6, 0x3e, 0xbd, 0x3a, 0x57, 0xa8, 0x30, 0x14, + 0xe3, 0xfa, 0xb6, 0x7b, 0x1f, 0xbe, 0x13, 0xda, 0x9b, 0x5b, 0x5c, 0x17, 0x8b, 0xfc, 0x19, 0xd9, + 0x25, 0xed, 0xaa, 0x3a, 0x3c, 0x69, 0x39, 0x20, 0x11, 0x19, 0xb5, 0x93, 0xd3, 0x90, 0x17, 0x92, + 0x45, 0xb4, 0x2f, 0xc1, 0x09, 0xab, 0x0b, 0xaf, 0x31, 0x1f, 0x1c, 0x45, 0x64, 0xd4, 0x4b, 0xf6, + 0x4b, 0x6c, 0x4e, 0x4f, 0x52, 0x69, 0x74, 0x3e, 0x38, 0x8e, 0xc8, 0xe8, 0x6c, 0x76, 0xf3, 0xfb, + 0x7d, 0x3d, 0x56, 0xda, 0x2f, 0xd7, 0xd9, 0x44, 0xa0, 0x89, 0x05, 0x3a, 0x83, 0xae, 0x39, 0xc6, + 0x4e, 0xae, 0x62, 0xff, 0x5a, 0x80, 0x9b, 0x4c, 0x85, 0x98, 0x4a, 0x69, 0xc1, 0xb9, 0x64, 0xd7, + 0x3f, 0xfc, 0x20, 0xb4, 0x1f, 0x9c, 0x1e, 0xc0, 0x64, 0x60, 0x6b, 0x70, 0xb0, 0x08, 0x4a, 0x87, + 0x81, 0x43, 0x3f, 0x5b, 0xd0, 0x8e, 0x09, 0xc8, 0xa0, 0x7f, 0x10, 0xa9, 0x01, 0xb0, 0x0b, 0xda, + 0xd9, 0x80, 0x56, 0x4b, 0x1f, 0xa6, 0x6d, 0x27, 0x4d, 0x9a, 0xdd, 0x7f, 0x96, 0x9c, 0x6c, 0x4b, + 0x4e, 0x7e, 0x4a, 0x4e, 0xde, 0x2a, 0xde, 0xda, 0x56, 0xbc, 0xf5, 0x55, 0xf1, 0xd6, 0xe3, 0xed, + 0xde, 0x47, 0x16, 0x14, 0xe4, 0xe3, 0x1c, 0xfc, 0x06, 0xed, 0xaa, 0x49, 0x2f, 0x20, 0x15, 0xd8, + 0x18, 0xad, 0x89, 0xff, 0x77, 0x96, 0x75, 0xc2, 0x92, 0xee, 0xfe, 0x02, 0x00, 0x00, 0xff, 0xff, + 0xb9, 0xf0, 0xdf, 0xf7, 0xd3, 0x01, 0x00, 0x00, +} + +func (m *GroupInfo) 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 *GroupInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GroupInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintCodec(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0x1a + } + if len(m.Description) > 0 { + i -= len(m.Description) + copy(dAtA[i:], m.Description) + i = encodeVarintCodec(dAtA, i, uint64(len(m.Description))) + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintCodec(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GroupMember) 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 *GroupMember) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GroupMember) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Weight != 0 { + i = encodeVarintCodec(dAtA, i, uint64(m.Weight)) + i-- + dAtA[i] = 0x18 + } + if len(m.Member) > 0 { + i -= len(m.Member) + copy(dAtA[i:], m.Member) + i = encodeVarintCodec(dAtA, i, uint64(len(m.Member))) + i-- + dAtA[i] = 0x12 + } + if len(m.Group) > 0 { + i -= len(m.Group) + copy(dAtA[i:], m.Group) + i = encodeVarintCodec(dAtA, i, uint64(len(m.Group))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintCodec(dAtA []byte, offset int, v uint64) int { + offset -= sovCodec(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GroupInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovCodec(uint64(m.GroupId)) + } + l = len(m.Description) + if l > 0 { + n += 1 + l + sovCodec(uint64(l)) + } + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovCodec(uint64(l)) + } + return n +} + +func (m *GroupMember) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Group) + if l > 0 { + n += 1 + l + sovCodec(uint64(l)) + } + l = len(m.Member) + if l > 0 { + n += 1 + l + sovCodec(uint64(l)) + } + if m.Weight != 0 { + n += 1 + sovCodec(uint64(m.Weight)) + } + return n +} + +func sovCodec(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCodec(x uint64) (n int) { + return sovCodec(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GroupInfo) 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 ErrIntOverflowCodec + } + 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: GroupInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GroupInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCodec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCodec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthCodec + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthCodec + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Description = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCodec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCodec + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCodec + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = append(m.Admin[:0], dAtA[iNdEx:postIndex]...) + if m.Admin == nil { + m.Admin = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCodec(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCodec + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthCodec + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GroupMember) 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 ErrIntOverflowCodec + } + 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: GroupMember: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GroupMember: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Group", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCodec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCodec + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCodec + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Group = append(m.Group[:0], dAtA[iNdEx:postIndex]...) + if m.Group == nil { + m.Group = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Member", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCodec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCodec + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCodec + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Member = append(m.Member[:0], dAtA[iNdEx:postIndex]...) + if m.Member == nil { + m.Member = []byte{} + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType) + } + m.Weight = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCodec + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Weight |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipCodec(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthCodec + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthCodec + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCodec(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCodec + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCodec + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCodec + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthCodec + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCodec + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCodec + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCodec = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCodec = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCodec = fmt.Errorf("proto: unexpected end of group") +) diff --git a/regen/orm/testdata/codec.proto b/regen/orm/testdata/codec.proto new file mode 100644 index 0000000000..84f8f2f038 --- /dev/null +++ b/regen/orm/testdata/codec.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +package testdata; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/regen/orm/testdata"; + +message GroupInfo { + uint64 group_id = 1; + string description = 2; + bytes admin = 3 [ (gogoproto.casttype) = + "github.com/cosmos/cosmos-sdk/types.AccAddress" ]; +} + +message GroupMember { + bytes group = 1 [ (gogoproto.casttype) = + "github.com/cosmos/cosmos-sdk/types.AccAddress" ]; + bytes member = 2 [ (gogoproto.casttype) = + "github.com/cosmos/cosmos-sdk/types.AccAddress" ]; + uint64 weight = 3; +} diff --git a/regen/orm/testdata/model.go b/regen/orm/testdata/model.go new file mode 100644 index 0000000000..28b77df969 --- /dev/null +++ b/regen/orm/testdata/model.go @@ -0,0 +1,28 @@ +package testdata + +import ( + "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + ErrTest = errors.Register("orm_testdata", 9999, "test") +) + +func (g GroupMember) PrimaryKeyFields() []interface{} { + return []interface{}{[]byte(g.Group), []byte(g.Member)} +} + +func (g GroupInfo) PrimaryKeyFields() []interface{} { + return []interface{}{g.GroupId} +} + +func (g GroupInfo) ValidateBasic() error { + if g.Description == "invalid" { + return errors.Wrap(ErrTest, "description") + } + return nil +} + +func (g GroupMember) ValidateBasic() error { + return nil +} diff --git a/regen/orm/testsupport.go b/regen/orm/testsupport.go new file mode 100644 index 0000000000..3f262150fb --- /dev/null +++ b/regen/orm/testsupport.go @@ -0,0 +1,135 @@ +package orm + +import ( + "fmt" + "io" + + "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/store/gaskv" + "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" + dbm "github.com/tendermint/tm-db" +) + +type MockContext struct { + db *dbm.MemDB + store types.CommitMultiStore +} + +func NewMockContext() *MockContext { + db := dbm.NewMemDB() + return &MockContext{ + db: dbm.NewMemDB(), + store: store.NewCommitMultiStore(db), + } +} + +func (m MockContext) KVStore(key sdk.StoreKey) sdk.KVStore { + if s := m.store.GetCommitKVStore(key); s != nil { + return s + } + m.store.MountStoreWithDB(key, sdk.StoreTypeIAVL, m.db) + if err := m.store.LoadLatestVersion(); err != nil { + panic(err) + } + return m.store.GetCommitKVStore(key) +} + +type debuggingGasMeter struct { + g types.GasMeter +} + +func (d debuggingGasMeter) GasConsumed() types.Gas { + return d.g.GasConsumed() +} + +func (d debuggingGasMeter) GasConsumedToLimit() types.Gas { + return d.g.GasConsumedToLimit() +} + +func (d debuggingGasMeter) RefundGas(amount uint64, descriptor string) { + d.g.RefundGas(amount, descriptor) +} + +func (d debuggingGasMeter) Limit() types.Gas { + return d.g.Limit() +} + +func (d debuggingGasMeter) ConsumeGas(amount types.Gas, descriptor string) { + fmt.Printf("++ Consuming gas: %q :%d\n", descriptor, amount) + d.g.ConsumeGas(amount, descriptor) +} + +func (d debuggingGasMeter) IsPastLimit() bool { + return d.g.IsPastLimit() +} + +func (d debuggingGasMeter) IsOutOfGas() bool { + return d.g.IsOutOfGas() +} + +func (d debuggingGasMeter) String() string { + return d.g.String() +} + +type GasCountingMockContext struct { + parent HasKVStore + GasMeter sdk.GasMeter +} + +func NewGasCountingMockContext(parent HasKVStore) *GasCountingMockContext { + return &GasCountingMockContext{ + parent: parent, + GasMeter: &debuggingGasMeter{sdk.NewInfiniteGasMeter()}, + } +} + +func (g GasCountingMockContext) KVStore(key sdk.StoreKey) sdk.KVStore { + return gaskv.NewStore(g.parent.KVStore(key), g.GasMeter, types.KVGasConfig()) +} + +func (g GasCountingMockContext) GasConsumed() types.Gas { + return g.GasMeter.GasConsumed() +} + +func (g *GasCountingMockContext) ResetGasMeter() { + g.GasMeter = sdk.NewInfiniteGasMeter() +} + +type AlwaysPanicKVStore struct{} + +func (a AlwaysPanicKVStore) GetStoreType() types.StoreType { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) CacheWrap() types.CacheWrap { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) CacheWrapWithTrace(w io.Writer, tc types.TraceContext) types.CacheWrap { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) Get(key []byte) []byte { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) Has(key []byte) bool { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) Set(key, value []byte) { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) Delete(key []byte) { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) Iterator(start, end []byte) types.Iterator { + panic("Not implemented") +} + +func (a AlwaysPanicKVStore) ReverseIterator(start, end []byte) types.Iterator { + panic("Not implemented") +} diff --git a/regen/orm/uint64_index.go b/regen/orm/uint64_index.go new file mode 100644 index 0000000000..98e9b8cf63 --- /dev/null +++ b/regen/orm/uint64_index.go @@ -0,0 +1,85 @@ +package orm + +import ( + "github.com/cosmos/cosmos-sdk/types/query" +) + +// UInt64IndexerFunc creates one or multiple multiKeyIndex keys of type uint64 for the source object. +type UInt64IndexerFunc func(value interface{}) ([]uint64, error) + +// UInt64MultiKeyAdapter converts UInt64IndexerFunc to IndexerFunc +func UInt64MultiKeyAdapter(indexer UInt64IndexerFunc) IndexerFunc { + return func(value interface{}) ([]RowID, error) { + d, err := indexer(value) + if err != nil { + return nil, err + } + r := make([]RowID, len(d)) + for i, v := range d { + r[i] = EncodeSequence(v) + } + return r, nil + } +} + +// UInt64Index is a typed index. +type UInt64Index struct { + multiKeyIndex MultiKeyIndex +} + +// NewUInt64Index creates a typed secondary index +func NewUInt64Index(builder Indexable, prefix byte, indexer UInt64IndexerFunc) UInt64Index { + return UInt64Index{ + multiKeyIndex: NewIndex(builder, prefix, UInt64MultiKeyAdapter(indexer)), + } +} + +// Has checks if a key exists. Panics on nil key. +func (i UInt64Index) Has(ctx HasKVStore, key uint64) bool { + return i.multiKeyIndex.Has(ctx, EncodeSequence(key)) +} + +// Get returns a result iterator for the searchKey. Parameters must not be nil. +func (i UInt64Index) Get(ctx HasKVStore, searchKey uint64) (Iterator, error) { + return i.multiKeyIndex.Get(ctx, EncodeSequence(searchKey)) +} + +// GetPaginated creates an iterator for the searchKey +// starting from pageRequest.Key if provided. +// The pageRequest.Key is the rowID while searchKey is a MultiKeyIndex key. +func (i UInt64Index) GetPaginated(ctx HasKVStore, searchKey uint64, pageRequest *query.PageRequest) (Iterator, error) { + return i.multiKeyIndex.GetPaginated(ctx, EncodeSequence(searchKey), pageRequest) +} + +// PrefixScan returns an Iterator over a domain of keys in ascending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a PrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. +// Example: +// it, err := idx.PrefixScan(ctx, start, end) +// if err !=nil { +// return err +// } +// const defaultLimit = 20 +// it = LimitIterator(it, defaultLimit) +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (i UInt64Index) PrefixScan(ctx HasKVStore, start, end uint64) (Iterator, error) { + return i.multiKeyIndex.PrefixScan(ctx, EncodeSequence(start), EncodeSequence(end)) +} + +// ReversePrefixScan returns an Iterator over a domain of keys in descending order. End is exclusive. +// Start is an MultiKeyIndex key or prefix. It must be less than end, or the Iterator is invalid and error is returned. +// Iterator must be closed by caller. +// To iterate over entire domain, use PrefixScan(nil, nil) +// +// WARNING: The use of a ReversePrefixScan can be very expensive in terms of Gas. Please make sure you do not expose +// this as an endpoint to the public without further limits. See `LimitIterator` +// +// CONTRACT: No writes may happen within a domain while an iterator exists over it. +func (i UInt64Index) ReversePrefixScan(ctx HasKVStore, start, end uint64) (Iterator, error) { + return i.multiKeyIndex.ReversePrefixScan(ctx, EncodeSequence(start), EncodeSequence(end)) +} diff --git a/regen/orm/uint64_index_test.go b/regen/orm/uint64_index_test.go new file mode 100644 index 0000000000..5582c9338e --- /dev/null +++ b/regen/orm/uint64_index_test.go @@ -0,0 +1,163 @@ +package orm_test + +import ( + "errors" + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/orm/testdata" +) + +func TestUInt64Index(t *testing.T) { + interfaceRegistry := types.NewInterfaceRegistry() + cdc := codec.NewProtoCodec(interfaceRegistry) + + storeKey := sdk.NewKVStoreKey("test") + + const anyPrefix = 0x10 + tableBuilder := orm.NewPrimaryKeyTableBuilder(anyPrefix, storeKey, &testdata.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + myIndex := orm.NewUInt64Index(tableBuilder, GroupMemberByMemberIndexPrefix, func(val interface{}) ([]uint64, error) { + return []uint64{uint64(val.(*testdata.GroupMember).Member[0])}, nil + }) + myTable := tableBuilder.Build() + + ctx := orm.NewMockContext() + + m := testdata.GroupMember{ + Group: sdk.AccAddress(orm.EncodeSequence(1)), + Member: sdk.AccAddress([]byte("member-address")), + Weight: 10, + } + err := myTable.Create(ctx, &m) + require.NoError(t, err) + + indexedKey := uint64('m') + + // Has + assert.True(t, myIndex.Has(ctx, indexedKey)) + + // Get + it, err := myIndex.Get(ctx, indexedKey) + require.NoError(t, err) + var loaded testdata.GroupMember + rowID, err := it.LoadNext(&loaded) + require.NoError(t, err) + require.Equal(t, uint64(0x800000000000000), orm.DecodeSequence(rowID)) + require.Equal(t, m, loaded) + + // GetPaginated + cases := map[string]struct { + pageReq *query.PageRequest + expErr bool + }{ + "nil key": { + pageReq: &query.PageRequest{Key: nil}, + expErr: false, + }, + "after indexed key": { + pageReq: &query.PageRequest{Key: []byte{byte('m')}}, + expErr: true, + }, + } + + for testName, tc := range cases { + t.Run(testName, func(t *testing.T) { + it, err := myIndex.GetPaginated(ctx, indexedKey, tc.pageReq) + require.NoError(t, err) + rowID, err := it.LoadNext(&loaded) + if tc.expErr { // iterator done + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, orm.RowID(orm.PrimaryKey(&m)), rowID) + require.Equal(t, m, loaded) + } + }) + } + + // PrefixScan match + it, err = myIndex.PrefixScan(ctx, 0, 255) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.NoError(t, err) + require.Equal(t, uint64(0x800000000000000), orm.DecodeSequence(rowID)) + require.Equal(t, m, loaded) + + // PrefixScan no match + it, err = myIndex.PrefixScan(ctx, indexedKey+1, 255) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.Error(t, orm.ErrIteratorDone, err) + + // ReversePrefixScan match + it, err = myIndex.ReversePrefixScan(ctx, 0, 255) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.NoError(t, err) + require.Equal(t, uint64(0x800000000000000), orm.DecodeSequence(rowID)) + require.Equal(t, m, loaded) + + // ReversePrefixScan no match + it, err = myIndex.ReversePrefixScan(ctx, indexedKey+1, 255) + require.NoError(t, err) + rowID, err = it.LoadNext(&loaded) + require.Error(t, orm.ErrIteratorDone, err) +} + +func TestUInt64MultiKeyAdapter(t *testing.T) { + specs := map[string]struct { + srcFunc orm.UInt64IndexerFunc + exp []orm.RowID + expErr error + }{ + "single key": { + srcFunc: func(value interface{}) ([]uint64, error) { + return []uint64{1}, nil + }, + exp: []orm.RowID{{0, 0, 0, 0, 0, 0, 0, 1}}, + }, + "multi key": { + srcFunc: func(value interface{}) ([]uint64, error) { + return []uint64{1, 1 << 56}, nil + }, + exp: []orm.RowID{{0, 0, 0, 0, 0, 0, 0, 1}, {1, 0, 0, 0, 0, 0, 0, 0}}, + }, + "empty key": { + srcFunc: func(value interface{}) ([]uint64, error) { + return []uint64{}, nil + }, + exp: []orm.RowID{}, + }, + "nil key": { + srcFunc: func(value interface{}) ([]uint64, error) { + return nil, nil + }, + exp: []orm.RowID{}, + }, + "error case": { + srcFunc: func(value interface{}) ([]uint64, error) { + return nil, errors.New("test") + }, + expErr: errors.New("test"), + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + fn := orm.UInt64MultiKeyAdapter(spec.srcFunc) + r, err := fn(nil) + if spec.expErr != nil { + require.Equal(t, spec.expErr, err) + return + } + require.NoError(t, err) + assert.Equal(t, spec.exp, r) + }) + } +} diff --git a/regen/types/address.go b/regen/types/address.go new file mode 100644 index 0000000000..11b83ce01e --- /dev/null +++ b/regen/types/address.go @@ -0,0 +1,13 @@ +package types + +import "crypto/sha256" + +func AddressHash(prefix string, contents []byte) []byte { + preImage := []byte(prefix) + if len(contents) != 0 { + preImage = append(preImage, 0) + preImage = append(preImage, contents...) + } + sum := sha256.Sum256(preImage) + return sum[:20] +} diff --git a/regen/types/conn.go b/regen/types/conn.go new file mode 100644 index 0000000000..936aa167c1 --- /dev/null +++ b/regen/types/conn.go @@ -0,0 +1,14 @@ +package types + +import ( + "context" + + "google.golang.org/grpc" +) + +type InvokerConn interface { + grpc.ClientConnInterface + Invoker(methodName string) (Invoker, error) +} + +type Invoker func(ctx context.Context, request, response interface{}, opts ...interface{}) error diff --git a/regen/types/context.go b/regen/types/context.go new file mode 100644 index 0000000000..40b8f0eb8b --- /dev/null +++ b/regen/types/context.go @@ -0,0 +1,33 @@ +package types + +import ( + "context" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type Context struct { + sdk.Context +} + +var _ context.Context = Context{} + +func (c Context) Deadline() (deadline time.Time, ok bool) { + return c.Context.Context().Deadline() +} + +func (c Context) Done() <-chan struct{} { + return c.Context.Context().Done() +} + +func (c Context) Err() error { + return c.Context.Context().Err() +} + +func UnwrapSDKContext(ctx context.Context) Context { + if sdkCtx, ok := ctx.(Context); ok { + return sdkCtx + } + return Context{sdk.UnwrapSDKContext(ctx)} +} diff --git a/regen/types/id.go b/regen/types/id.go new file mode 100644 index 0000000000..92fd410b87 --- /dev/null +++ b/regen/types/id.go @@ -0,0 +1,12 @@ +package types + +import sdk "github.com/cosmos/cosmos-sdk/types" + +type ModuleID struct { + ModuleName string + Path []byte +} + +func (m ModuleID) Address() sdk.AccAddress { + return AddressHash(m.ModuleName, m.Path) +} diff --git a/regen/types/math/dec.go b/regen/types/math/dec.go new file mode 100644 index 0000000000..b38cb5e4ec --- /dev/null +++ b/regen/types/math/dec.go @@ -0,0 +1,173 @@ +package math + +import ( + "fmt" + + "github.com/cockroachdb/apd/v2" + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Dec is a wrapper struct around apd.Decimal that does no mutation of apd.Decimal's when performing +// arithmetic, instead creating a new apd.Decimal for every operation ensuring usage is safe. +// +// Using apd.Decimal directly can be unsafe because apd operations mutate the underlying Decimal, +// but when copying the big.Int structure can be shared between Decimal instances causing corruption. +// This was originally discovered in regen0-network/mainnet#15. +type Dec struct { + dec apd.Decimal +} + +// In cosmos-sdk#7773, decimal128 (with 34 digits of precision) was suggested for performing +// Quo/Mult arithmetic generically across the SDK. Even though the SDK +// has yet to support a GDA with decimal128 (34 digits), we choose to utilize it here. +// https://github.com/cosmos/cosmos-sdk/issues/7773#issuecomment-725006142 +var dec128Context = apd.Context{ + Precision: 34, + MaxExponent: apd.MaxExponent, + MinExponent: apd.MinExponent, + Traps: apd.DefaultTraps, +} + +func NewDecFromString(s string) (Dec, error) { + d, _, err := apd.NewFromString(s) + if err != nil { + return Dec{}, err + } + return Dec{*d}, nil +} + +func NewNonNegativeDecFromString(s string) (Dec, error) { + d, err := NewDecFromString(s) + if err != nil { + return Dec{}, err + } + if d.IsNegative() { + return Dec{}, fmt.Errorf("cannot parse non negative decimal: %s", d.String()) + } + return d, nil +} + +func NewNonNegativeFixedDecFromString(s string, max uint32) (Dec, error) { + d, err := NewDecFromString(s) + if err != nil { + return Dec{}, err + } + if d.IsNegative() { + return Dec{}, fmt.Errorf("cannot parse non negative decimal: %s", d.String()) + } + if d.NumDecimalPlaces() > max { + return Dec{}, fmt.Errorf("%s exceeds maximum decimal places: %d", s, max) + } + return d, nil +} + +func NewPositiveFixedDecFromString(s string, max uint32) (Dec, error) { + d, err := NewDecFromString(s) + if err != nil { + return Dec{}, err + } + if !d.IsPositive() { + return Dec{}, fmt.Errorf("%s is not a positive decimal", d.String()) + } + if d.NumDecimalPlaces() > max { + return Dec{}, fmt.Errorf("%s exceeds maximum decimal places: %d", s, max) + } + return d, nil +} + +func NewDecFromInt64(x int64) Dec { + var res Dec + res.dec.SetInt64(x) + return res +} + +// Add returns a new Dec with value `x+y` without mutating any argument and error if +// there is an overflow. +func (x Dec) Add(y Dec) (Dec, error) { + var z Dec + _, err := apd.BaseContext.Add(&z.dec, &x.dec, &y.dec) + return z, errors.Wrap(err, "decimal addition error") +} + +// Sub returns a new Dec with value `x-y` without mutating any argument and error if +// there is an overflow. +func (x Dec) Sub(y Dec) (Dec, error) { + var z Dec + _, err := apd.BaseContext.Sub(&z.dec, &x.dec, &y.dec) + return z, errors.Wrap(err, "decimal subtraction error") +} + +// Quo returns a new Dec with value `x/y` (formatted as decimal128, 34 digit precision) without mutating any +// argument and error if there is an overflow. +func (x Dec) Quo(y Dec) (Dec, error) { + var z Dec + _, err := dec128Context.Quo(&z.dec, &x.dec, &y.dec) + return z, errors.Wrap(err, "decimal quotient error") +} + +// QuoInteger returns a new integral Dec with value `x/y` (formatted as decimal128, with 34 digit precision) +// without mutating any argument and error if there is an overflow. +func (x Dec) QuoInteger(y Dec) (Dec, error) { + var z Dec + _, err := dec128Context.QuoInteger(&z.dec, &x.dec, &y.dec) + return z, errors.Wrap(err, "decimal quotient error") +} + +// Rem returns the integral remainder from `x/y` (formatted as decimal128, with 34 digit precision) without +// mutating any argument and error if the integer part of x/y cannot fit in 34 digit precision +func (x Dec) Rem(y Dec) (Dec, error) { + var z Dec + _, err := dec128Context.Rem(&z.dec, &x.dec, &y.dec) + return z, errors.Wrap(err, "decimal remainder error") +} + +// Mul returns a new Dec with value `x*y` (formatted as decimal128, with 34 digit precision) without +// mutating any argument and error if there is an overflow. +func (x Dec) Mul(y Dec) (Dec, error) { + var z Dec + _, err := dec128Context.Mul(&z.dec, &x.dec, &y.dec) + return z, errors.Wrap(err, "decimal multiplication error") +} + +func (x Dec) Int64() (int64, error) { + return x.dec.Int64() +} + +func (x Dec) String() string { + return x.dec.Text('f') +} + +func (x Dec) Cmp(y Dec) int { + return x.dec.Cmp(&y.dec) +} + +func (x Dec) IsEqual(y Dec) bool { + return x.dec.Cmp(&y.dec) == 0 +} + +func (x Dec) IsZero() bool { + return x.dec.IsZero() +} + +func (x Dec) IsNegative() bool { + return x.dec.Negative && !x.dec.IsZero() +} + +func (x Dec) IsPositive() bool { + return !x.dec.Negative && !x.dec.IsZero() +} + +// NumDecimalPlaces returns the number of decimal places in x. +func (x Dec) NumDecimalPlaces() uint32 { + exp := x.dec.Exponent + if exp >= 0 { + return 0 + } + return uint32(-exp) +} + +func (x Dec) Reduce() (Dec, int) { + y := Dec{} + _, n := y.dec.Reduce(&x.dec) + return y, n +} diff --git a/regen/types/math/dec_test.go b/regen/types/math/dec_test.go new file mode 100644 index 0000000000..dcbd29a1db --- /dev/null +++ b/regen/types/math/dec_test.go @@ -0,0 +1,485 @@ +package math + +import ( + "fmt" + "regexp" + "strconv" + "testing" + + "github.com/stretchr/testify/require" + "pgregory.net/rapid" +) + +func TestDec(t *testing.T) { + + // Property tests + t.Run("TestNewDecFromInt64", rapid.MakeCheck(testDecInt64)) + + // Properties about addition + t.Run("TestAddLeftIdentity", rapid.MakeCheck(testAddLeftIdentity)) + t.Run("TestAddRightIdentity", rapid.MakeCheck(testAddRightIdentity)) + t.Run("TestAddCommutative", rapid.MakeCheck(testAddCommutative)) + t.Run("TestAddAssociative", rapid.MakeCheck(testAddAssociative)) + + // Properties about subtraction + t.Run("TestSubRightIdentity", rapid.MakeCheck(testSubRightIdentity)) + t.Run("TestSubZero", rapid.MakeCheck(testSubZero)) + + // Properties about multiplication + t.Run("TestMulLeftIdentity", rapid.MakeCheck(testMulLeftIdentity)) + t.Run("TestMulRightIdentity", rapid.MakeCheck(testMulRightIdentity)) + t.Run("TestMulCommutative", rapid.MakeCheck(testMulCommutative)) + t.Run("TestMulAssociative", rapid.MakeCheck(testMulAssociative)) + t.Run("TestZeroIdentity", rapid.MakeCheck(testMulZero)) + + // Properties about division + t.Run("TestDivisionBySelf", rapid.MakeCheck(testSelfQuo)) + t.Run("TestDivisionByOne", rapid.MakeCheck(testQuoByOne)) + + // Properties combining operations + t.Run("TestSubAdd", rapid.MakeCheck(testSubAdd)) + t.Run("TestAddSub", rapid.MakeCheck(testAddSub)) + t.Run("TestMulQuoA", rapid.MakeCheck(testMulQuoA)) + t.Run("TestMulQuoB", rapid.MakeCheck(testMulQuoB)) + + // Properties about comparision and equality + t.Run("TestCmpInverse", rapid.MakeCheck(testCmpInverse)) + t.Run("TestEqualCommutative", rapid.MakeCheck(testEqualCommutative)) + + // Properties about tests on a single Dec + t.Run("TestIsZero", rapid.MakeCheck(testIsZero)) + t.Run("TestIsNegative", rapid.MakeCheck(testIsNegative)) + t.Run("TestIsPositive", rapid.MakeCheck(testIsPositive)) + t.Run("TestNumDecimalPlaces", rapid.MakeCheck(testNumDecimalPlaces)) + + // Unit tests + zero := Dec{} + one := NewDecFromInt64(1) + two := NewDecFromInt64(2) + three := NewDecFromInt64(3) + four := NewDecFromInt64(4) + five := NewDecFromInt64(5) + minusOne := NewDecFromInt64(-1) + + onePointOneFive, err := NewDecFromString("1.15") + require.NoError(t, err) + twoPointThreeFour, err := NewDecFromString("2.34") + require.NoError(t, err) + threePointFourNine, err := NewDecFromString("3.49") + require.NoError(t, err) + onePointFourNine, err := NewDecFromString("1.49") + require.NoError(t, err) + minusFivePointZero, err := NewDecFromString("-5.0") + require.NoError(t, err) + + res, err := two.Add(zero) + require.NoError(t, err) + require.True(t, res.IsEqual(two)) + + res, err = five.Sub(two) + require.NoError(t, err) + require.True(t, res.IsEqual(three)) + + res, err = SafeSubBalance(five, two) + require.NoError(t, err) + require.True(t, res.IsEqual(three)) + + res, err = SafeSubBalance(two, five) + require.Error(t, err, "Expected insufficient funds error") + + res, err = SafeAddBalance(three, two) + require.NoError(t, err) + require.True(t, res.IsEqual(five)) + + res, err = SafeAddBalance(minusFivePointZero, five) + require.Error(t, err, "Expected ErrInvalidRequest") + + res, err = four.Quo(two) + require.NoError(t, err) + require.True(t, res.IsEqual(two)) + + res, err = five.QuoInteger(two) + require.NoError(t, err) + require.True(t, res.IsEqual(two)) + + res, err = five.Rem(two) + require.NoError(t, err) + require.True(t, res.IsEqual(one)) + + x, err := four.Int64() + require.NoError(t, err) + require.Equal(t, int64(4), x) + + require.Equal(t, "5", five.String()) + + res, err = onePointOneFive.Add(twoPointThreeFour) + require.NoError(t, err) + require.True(t, res.IsEqual(threePointFourNine)) + + res, err = threePointFourNine.Sub(two) + require.NoError(t, err) + require.True(t, res.IsEqual(onePointFourNine)) + + res, err = minusOne.Sub(four) + require.NoError(t, err) + require.True(t, res.IsEqual(minusFivePointZero)) + + require.True(t, zero.IsZero()) + require.False(t, zero.IsPositive()) + require.False(t, zero.IsNegative()) + + require.False(t, one.IsZero()) + require.True(t, one.IsPositive()) + require.False(t, one.IsNegative()) + + require.False(t, minusOne.IsZero()) + require.False(t, minusOne.IsPositive()) + require.True(t, minusOne.IsNegative()) +} + +// TODO: Think a bit more about the probability distribution of Dec +var genDec *rapid.Generator = rapid.Custom(func(t *rapid.T) Dec { + f := rapid.Float64().Draw(t, "f").(float64) + dec, err := NewDecFromString(fmt.Sprintf("%g", f)) + require.NoError(t, err) + return dec +}) + +// A Dec value and the float used to create it +type floatAndDec struct { + float float64 + dec Dec +} + +// Generate a Dec value along with the float used to create it +var genFloatAndDec *rapid.Generator = rapid.Custom(func(t *rapid.T) floatAndDec { + f := rapid.Float64().Draw(t, "f").(float64) + dec, err := NewDecFromString(fmt.Sprintf("%g", f)) + require.NoError(t, err) + return floatAndDec{f, dec} +}) + +// Property: n == NewDecFromInt64(n).Int64() +func testDecInt64(t *rapid.T) { + nIn := rapid.Int64().Draw(t, "n").(int64) + nOut, err := NewDecFromInt64(nIn).Int64() + + require.NoError(t, err) + require.Equal(t, nIn, nOut) +} + +// Property: 0 + a == a +func testAddLeftIdentity(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + zero := NewDecFromInt64(0) + + b, err := zero.Add(a) + require.NoError(t, err) + + require.True(t, a.IsEqual(b)) +} + +// Property: a + 0 == a +func testAddRightIdentity(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + zero := NewDecFromInt64(0) + + b, err := a.Add(zero) + require.NoError(t, err) + + require.True(t, a.IsEqual(b)) +} + +// Property: a + b == b + a +func testAddCommutative(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + c, err := a.Add(b) + require.NoError(t, err) + + d, err := b.Add(a) + require.NoError(t, err) + + require.True(t, c.IsEqual(d)) +} + +// Property: (a + b) + c == a + (b + c) +func testAddAssociative(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + c := genDec.Draw(t, "c").(Dec) + + // (a + b) + c + d, err := a.Add(b) + require.NoError(t, err) + + e, err := d.Add(c) + require.NoError(t, err) + + // a + (b + c) + f, err := b.Add(c) + require.NoError(t, err) + + g, err := a.Add(f) + require.NoError(t, err) + + require.True(t, e.IsEqual(g)) +} + +// Property: a - 0 == a +func testSubRightIdentity(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + zero := NewDecFromInt64(0) + + b, err := a.Sub(zero) + require.NoError(t, err) + + require.True(t, a.IsEqual(b)) +} + +// Property: a - a == 0 +func testSubZero(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + zero := NewDecFromInt64(0) + + b, err := a.Sub(a) + require.NoError(t, err) + + require.True(t, b.IsEqual(zero)) +} + +// Property: 1 * a == a +func testMulLeftIdentity(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + one := NewDecFromInt64(1) + + b, err := one.Mul(a) + require.NoError(t, err) + + require.True(t, a.IsEqual(b)) +} + +// Property: a * 1 == a +func testMulRightIdentity(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + one := NewDecFromInt64(1) + + b, err := a.Mul(one) + require.NoError(t, err) + + require.True(t, a.IsEqual(b)) +} + +// Property: a * b == b * a +func testMulCommutative(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + c, err := a.Mul(b) + require.NoError(t, err) + + d, err := b.Mul(a) + require.NoError(t, err) + + require.True(t, c.IsEqual(d)) +} + +// Property: (a * b) * c == a * (b * c) +func testMulAssociative(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + c := genDec.Draw(t, "c").(Dec) + + // (a * b) * c + d, err := a.Mul(b) + require.NoError(t, err) + + e, err := d.Mul(c) + require.NoError(t, err) + + // a * (b * c) + f, err := b.Mul(c) + require.NoError(t, err) + + g, err := a.Mul(f) + require.NoError(t, err) + + require.True(t, e.IsEqual(g)) +} + +// Property: (a - b) + b == a +func testSubAdd(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + c, err := a.Sub(b) + require.NoError(t, err) + + d, err := c.Add(b) + require.NoError(t, err) + + require.True(t, a.IsEqual(d)) +} + +// Property: (a + b) - b == a +func testAddSub(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + c, err := a.Add(b) + require.NoError(t, err) + + d, err := c.Sub(b) + require.NoError(t, err) + + require.True(t, a.IsEqual(d)) +} + +// Property: a * 0 = 0 +func testMulZero(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + zero := Dec{} + + c, err := a.Mul(zero) + require.NoError(t, err) + require.True(t, c.IsZero()) +} + +// Property: a/a = 1 +func testSelfQuo(t *rapid.T) { + decNotZero := func(d Dec) bool { return !d.IsZero() } + a := genDec.Filter(decNotZero).Draw(t, "a").(Dec) + one := NewDecFromInt64(1) + + b, err := a.Quo(a) + require.NoError(t, err) + require.True(t, one.IsEqual(b)) +} + +// Property: a/1 = a +func testQuoByOne(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + one := NewDecFromInt64(1) + + b, err := a.Quo(one) + require.NoError(t, err) + require.True(t, a.IsEqual(b)) +} + +// Property: (a * b) / a == b +func testMulQuoA(t *rapid.T) { + decNotZero := func(d Dec) bool { return !d.IsZero() } + a := genDec.Filter(decNotZero).Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + c, err := a.Mul(b) + require.NoError(t, err) + + d, err := c.Quo(a) + require.NoError(t, err) + + require.True(t, b.IsEqual(d)) +} + +// Property: (a * b) / b == a +func testMulQuoB(t *rapid.T) { + decNotZero := func(d Dec) bool { return !d.IsZero() } + a := genDec.Draw(t, "a").(Dec) + b := genDec.Filter(decNotZero).Draw(t, "b").(Dec) + + c, err := a.Mul(b) + require.NoError(t, err) + + d, err := c.Quo(b) + require.NoError(t, err) + + require.True(t, a.IsEqual(d)) +} + +// Property: Cmp(a, b) == -Cmp(b, a) +func testCmpInverse(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + require.Equal(t, a.Cmp(b), -b.Cmp(a)) +} + +// Property: IsEqual(a, b) == IsEqual(b, a) +func testEqualCommutative(t *rapid.T) { + a := genDec.Draw(t, "a").(Dec) + b := genDec.Draw(t, "b").(Dec) + + require.Equal(t, a.IsEqual(b), b.IsEqual(a)) +} + +// Property: isZero(f) == isZero(NewDecFromString(f.String())) +func testIsZero(t *rapid.T) { + floatAndDec := genFloatAndDec.Draw(t, "floatAndDec").(floatAndDec) + f, dec := floatAndDec.float, floatAndDec.dec + + require.Equal(t, f == 0, dec.IsZero()) + +} + +// Property: isNegative(f) == isNegative(NewDecFromString(f.String())) +func testIsNegative(t *rapid.T) { + floatAndDec := genFloatAndDec.Draw(t, "floatAndDec").(floatAndDec) + f, dec := floatAndDec.float, floatAndDec.dec + + require.Equal(t, f < 0, dec.IsNegative()) +} + +// Property: isPositive(f) == isPositive(NewDecFromString(f.String())) +func testIsPositive(t *rapid.T) { + floatAndDec := genFloatAndDec.Draw(t, "floatAndDec").(floatAndDec) + f, dec := floatAndDec.float, floatAndDec.dec + + require.Equal(t, f > 0, dec.IsPositive()) +} + +// Property: floatDecimalPlaces(f) == NumDecimalPlaces(NewDecFromString(f.String())) +func testNumDecimalPlaces(t *rapid.T) { + floatAndDec := genFloatAndDec.Draw(t, "floatAndDec").(floatAndDec) + f, dec := floatAndDec.float, floatAndDec.dec + + require.Equal(t, floatDecimalPlaces(t, f), dec.NumDecimalPlaces()) +} + +func floatDecimalPlaces(t *rapid.T, f float64) uint32 { + reScientific := regexp.MustCompile(`^\-?(?:[[:digit:]]+(?:\.([[:digit:]]+))?|\.([[:digit:]]+))(?:e?(?:\+?([[:digit:]]+)|(-[[:digit:]]+)))?$`) + fStr := fmt.Sprintf("%g", f) + matches := reScientific.FindAllStringSubmatch(fStr, 1) + if len(matches) != 1 { + t.Fatalf("Didn't match float: %g", f) + } + + // basePlaces is the number of decimal places in the decimal part of the + // string + basePlaces := 0 + if matches[0][1] != "" { + basePlaces = len(matches[0][1]) + } else if matches[0][2] != "" { + basePlaces = len(matches[0][2]) + } + t.Logf("Base places: %d", basePlaces) + + // exp is the exponent + exp := 0 + if matches[0][3] != "" { + var err error + exp, err = strconv.Atoi(matches[0][3]) + require.NoError(t, err) + } else if matches[0][4] != "" { + var err error + exp, err = strconv.Atoi(matches[0][4]) + require.NoError(t, err) + } + + // Subtract exponent from base and check if negative + if res := basePlaces - exp; res <= 0 { + return 0 + } else { + return uint32(res) + } +} diff --git a/regen/types/math/math.go b/regen/types/math/math.go new file mode 100644 index 0000000000..9416271131 --- /dev/null +++ b/regen/types/math/math.go @@ -0,0 +1,147 @@ +// Package math provides helper functions for doing mathematical calculations and parsing for the ecocredit module. +package math + +import ( + "fmt" + + "github.com/cockroachdb/apd/v2" + + "github.com/cosmos/cosmos-sdk/types/errors" +) + +// Deprecated: ParseNonNegativeDecimal parses a non-negative decimal or returns an error. +func ParseNonNegativeDecimal(x string) (*apd.Decimal, error) { + res, _, err := apd.NewFromString(x) + if err != nil || res.Sign() < 0 { + return nil, errors.Wrap(errors.ErrInvalidRequest, fmt.Sprintf("expected a non-negative decimal, got %s", x)) + } + + return res, nil +} + +// Deprecated: ParsePositiveDecimal parses a positive decimal or returns an error. +func ParsePositiveDecimal(x string) (*apd.Decimal, error) { + res, _, err := apd.NewFromString(x) + if err != nil || res.Sign() <= 0 { + return nil, errors.Wrap(errors.ErrInvalidRequest, fmt.Sprintf("expected a positive decimal, got %s", x)) + } + + return res, nil +} + +// Deprecated: DecimalString prints x as a floating point string. +func DecimalString(x *apd.Decimal) string { + return x.Text('f') +} + +// Deprecated: NumDecimalPlaces returns the number of decimal places in x. +func NumDecimalPlaces(x *apd.Decimal) uint32 { + if x.Exponent >= 0 { + return 0 + } + return uint32(-x.Exponent) +} + +// Deprecated: ParseNonNegativeDecimal parses a non-negative decimal with a fixed maxDecimalPlaces or returns an error. +func ParseNonNegativeFixedDecimal(x string, maxDecimalPlaces uint32) (*apd.Decimal, error) { + res, err := ParseNonNegativeDecimal(x) + if err != nil { + return nil, err + } + + err = requireMaxDecimals(res, maxDecimalPlaces) + if err != nil { + return nil, err + } + + return res, nil +} + +// Deprecated: ParsePositiveFixedDecimal parses a positive decimal with a fixed maxDecimalPlaces or returns an error. +func ParsePositiveFixedDecimal(x string, maxDecimalPlaces uint32) (*apd.Decimal, error) { + res, err := ParsePositiveDecimal(x) + if err != nil { + return nil, err + } + + err = requireMaxDecimals(res, maxDecimalPlaces) + if err != nil { + return nil, err + } + + return res, nil +} + +func requireMaxDecimals(x *apd.Decimal, maxDecimalPlaces uint32) error { + n := NumDecimalPlaces(x) + if n > maxDecimalPlaces { + return errors.Wrap(errors.ErrInvalidRequest, fmt.Sprintf("expected no more than %d decimal places in %s, got %d", maxDecimalPlaces, x, n)) + } + return nil +} + +var exactContext = apd.Context{ + Precision: 0, + MaxExponent: apd.MaxExponent, + MinExponent: apd.MinExponent, + Traps: apd.DefaultTraps | apd.Inexact | apd.Rounded, +} + +// Deprecated: Add adds x and y and stores the result in res with arbitrary precision or returns an error. +func Add(res, x, y *apd.Decimal) error { + _, err := exactContext.Add(res, x, y) + if err != nil { + return errors.Wrap(err, "decimal addition error") + } + return nil +} + +// Deprecated: SafeSub subtracts the value of x from y and stores the result in res with arbitrary precision only +// if the result will be non-negative. An insufficient funds error is returned if the result would be negative. +func SafeSub(res, x, y *apd.Decimal) error { + _, err := exactContext.Sub(res, x, y) + if err != nil { + return errors.Wrap(err, "decimal subtraction error") + } + + if res.Sign() < 0 { + return errors.ErrInsufficientFunds + } + + return nil +} + +// SafeSubBalance subtracts the value of y from x and returns the result with arbitrary precision. +// Returns with ErrInsufficientFunds error if the result is negative. +func SafeSubBalance(x Dec, y Dec) (Dec, error) { + var z Dec + _, err := exactContext.Sub(&z.dec, &x.dec, &y.dec) + if err != nil { + return z, errors.Wrap(err, "decimal subtraction error") + } + + if z.IsNegative() { + return z, errors.ErrInsufficientFunds + } + + return z, nil +} + +// SafeAddBalance adds the value of x+y and returns the result with arbitrary precision. +// Returns with ErrInvalidRequest error if either x or y is negative. +func SafeAddBalance(x Dec, y Dec) (Dec, error) { + var z Dec + + if x.IsNegative() || y.IsNegative() { + return z, errors.Wrap( + errors.ErrInvalidRequest, + fmt.Sprintf("AddBalance() requires two non-negative Dec parameters, but received %s and %s", x, y)) + } + + _, err := exactContext.Add(&z.dec, &x.dec, &y.dec) + if err != nil { + return z, errors.Wrap(err, "decimal subtraction error") + } + + return z, nil +} diff --git a/regen/types/math/math_test.go b/regen/types/math/math_test.go new file mode 100644 index 0000000000..dd1d79c2ad --- /dev/null +++ b/regen/types/math/math_test.go @@ -0,0 +1,34 @@ +package math + +import ( + "testing" + + "github.com/cockroachdb/apd/v2" + "github.com/stretchr/testify/require" +) + +func Test_CountDecPlaces(t *testing.T) { + tests := []struct { + x string + want int32 + reduced int32 + }{ + {"0", 0, 0}, + {"1.0", 1, 0}, + {"1.0000", 4, 0}, + {"1.23", 2, 2}, + {"100", 0, 0}, + {"0.0003", 4, 4}, + } + for _, tt := range tests { + t.Run(tt.x, func(t *testing.T) { + x, _, err := apd.NewFromString(tt.x) + require.NoError(t, err) + got := NumDecimalPlaces(x) + require.Equal(t, uint32(tt.want), got) + x, _ = x.Reduce(x) + got = NumDecimalPlaces(x) + require.Equal(t, uint32(tt.reduced), got) + }) + } +} diff --git a/regen/types/module/base.go b/regen/types/module/base.go new file mode 100644 index 0000000000..a73b4c1f59 --- /dev/null +++ b/regen/types/module/base.go @@ -0,0 +1,15 @@ +package module + +import "github.com/cosmos/cosmos-sdk/codec/types" + +// Module is the base module type that all modules (client and server) must satisfy. +type Module interface { + Name() string +} + +// TypeModule is an interface that modules should implement to register types. +type TypeModule interface { + Module + + RegisterInterfaces(types.InterfaceRegistry) +} diff --git a/regen/types/module/client/cli/module.go b/regen/types/module/client/cli/module.go new file mode 100644 index 0000000000..6f99e9b205 --- /dev/null +++ b/regen/types/module/client/cli/module.go @@ -0,0 +1,21 @@ +package cli + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/regen/types/module" +) + +// Module is an interface that modules should implement to integrate with the CLI framework. +type Module interface { + module.TypeModule + + DefaultGenesis(codec.JSONCodec) json.RawMessage + ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error + GetTxCmd() *cobra.Command + GetQueryCmd() *cobra.Command +} diff --git a/regen/types/module/client/grpc_gateway/module.go b/regen/types/module/client/grpc_gateway/module.go new file mode 100644 index 0000000000..4c6f73b69b --- /dev/null +++ b/regen/types/module/client/grpc_gateway/module.go @@ -0,0 +1,14 @@ +package grpc_gateway + +import ( + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/regen/types/module" + "github.com/grpc-ecosystem/grpc-gateway/runtime" +) + +// Module is an interface that modules should implement to register grpc-gateway routes. +type Module interface { + module.Module + + RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux) +} diff --git a/regen/types/module/genesis.go b/regen/types/module/genesis.go new file mode 100644 index 0000000000..00f41cfb30 --- /dev/null +++ b/regen/types/module/genesis.go @@ -0,0 +1,12 @@ +package module + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/regen/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +type InitGenesisHandler func(ctx types.Context, cdc codec.Codec, data json.RawMessage) ([]abci.ValidatorUpdate, error) +type ExportGenesisHandler func(ctx types.Context, cdc codec.Codec) (json.RawMessage, error) diff --git a/regen/types/module/server/derived_module_key.go b/regen/types/module/server/derived_module_key.go new file mode 100644 index 0000000000..bac0a1cbef --- /dev/null +++ b/regen/types/module/server/derived_module_key.go @@ -0,0 +1,51 @@ +package server + +import ( + "context" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/regen/types" + + "google.golang.org/grpc" +) + +type DerivedModuleKey struct { + moduleName string + path []byte + invokerFactory InvokerFactory +} + +var _ ModuleKey = DerivedModuleKey{} + +func (d DerivedModuleKey) Invoker(methodName string) (types.Invoker, error) { + return d.invokerFactory(CallInfo{ + Method: methodName, + Caller: d.ModuleID(), + }) +} + +func (d DerivedModuleKey) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, _ ...grpc.CallOption) error { + invoker, err := d.Invoker(method) + if err != nil { + return err + } + + return invoker(ctx, args, reply) +} + +func (d DerivedModuleKey) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("unsupported") +} + +func (d DerivedModuleKey) ModuleID() types.ModuleID { + return types.ModuleID{ + ModuleName: d.moduleName, + Path: d.path, + } +} + +func (d DerivedModuleKey) Address() sdk.AccAddress { + return d.ModuleID().Address() +} diff --git a/regen/types/module/server/manager.go b/regen/types/module/server/manager.go new file mode 100644 index 0000000000..3e2178b826 --- /dev/null +++ b/regen/types/module/server/manager.go @@ -0,0 +1,311 @@ +package server + +import ( + "encoding/json" + "errors" + "fmt" + "reflect" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/server/api" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkmodule "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/types/simulation" + gogogrpc "github.com/gogo/protobuf/grpc" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/regen/types" + "github.com/cosmos/cosmos-sdk/regen/types/module" + restmodule "github.com/cosmos/cosmos-sdk/regen/types/module/client/grpc_gateway" +) + +// Manager is the server module manager +type Manager struct { + baseApp *baseapp.BaseApp + cdc *codec.ProtoCodec + keys map[string]ModuleKey + modules []module.Module + router *router + requiredServices map[reflect.Type]bool + initGenesisHandlers map[string]module.InitGenesisHandler + exportGenesisHandlers map[string]module.ExportGenesisHandler + registerInvariantsHandler map[string]RegisterInvariantsHandler + weightedOperationsHandlers map[string]WeightedOperationsHandler +} + +// RegisterInvariants registers all module routes and module querier routes +func (mm *Manager) RegisterInvariants(ir sdk.InvariantRegistry) { + for _, invariant := range mm.registerInvariantsHandler { + if invariant != nil { + invariant(ir) + } + } +} + +// NewManager creates a new Manager +func NewManager(baseApp *baseapp.BaseApp, cdc *codec.ProtoCodec) *Manager { + return &Manager{ + baseApp: baseApp, + cdc: cdc, + keys: map[string]ModuleKey{}, + registerInvariantsHandler: map[string]RegisterInvariantsHandler{}, + initGenesisHandlers: map[string]module.InitGenesisHandler{}, + exportGenesisHandlers: map[string]module.ExportGenesisHandler{}, + router: &router{ + handlers: map[string]handler{}, + providedServices: map[reflect.Type]bool{}, + msgServiceRouter: baseApp.MsgServiceRouter(), + }, + requiredServices: map[reflect.Type]bool{}, + weightedOperationsHandlers: map[string]WeightedOperationsHandler{}, + } +} + +func (mm *Manager) GetWeightedOperationsHandlers() map[string]WeightedOperationsHandler { + return mm.weightedOperationsHandlers +} + +// RegisterGRPCGatewayRoutes registers all module grpc-gateway routes +func (mm *Manager) RegisterGRPCGatewayRoutes(apiSvr *api.Server) { + for _, m := range mm.modules { + // check if we actually have a grpc-gateway module, otherwise skip + serverMod, ok := m.(restmodule.Module) + if !ok { + continue + } + serverMod.RegisterGRPCGatewayRoutes(apiSvr.ClientCtx, apiSvr.GRPCGatewayRouter) + } +} + +// RegisterModules registers modules with the Manager and registers their services. +func (mm *Manager) RegisterModules(modules []module.Module) error { + mm.modules = modules + // First we register all interface types. This is done for all modules first before registering + // any services in case there are any weird dependencies that will cause service initialization to fail. + for _, mod := range modules { + // check if we actually have a server module, otherwise skip + serverMod, ok := mod.(Module) + if !ok { + continue + } + + serverMod.RegisterInterfaces(mm.cdc.InterfaceRegistry()) + } + + // Next we register services + for _, mod := range modules { + // check if we actually have a server module, otherwise skip + serverMod, ok := mod.(Module) + if !ok { + continue + } + + name := serverMod.Name() + + invokerFactory := mm.router.invokerFactory(name) + + key := &rootModuleKey{ + moduleName: name, + invokerFactory: invokerFactory, + } + + if _, found := mm.keys[name]; found { + return fmt.Errorf("module named %s defined twice", name) + } + + mm.keys[name] = key + mm.baseApp.MountStore(key, sdk.StoreTypeIAVL) + + msgRegistrar := registrar{ + router: mm.router, + baseServer: mm.baseApp.MsgServiceRouter(), + commitWrites: true, + moduleName: name, + } + + queryRegistrar := registrar{ + router: mm.router, + baseServer: mm.baseApp.GRPCQueryRouter(), + commitWrites: false, + moduleName: name, + } + + cfg := &configurator{ + msgServer: msgRegistrar, + queryServer: queryRegistrar, + key: key, + cdc: mm.cdc, + requiredServices: map[reflect.Type]bool{}, + } + + serverMod.RegisterServices(cfg) + mm.registerInvariantsHandler[name] = cfg.registerInvariantsHandler + mm.initGenesisHandlers[name] = cfg.initGenesisHandler + mm.exportGenesisHandlers[name] = cfg.exportGenesisHandler + + if cfg.weightedOperationHandler != nil { + mm.weightedOperationsHandlers[name] = cfg.weightedOperationHandler + } + + for typ := range cfg.requiredServices { + mm.requiredServices[typ] = true + } + + } + + return nil +} + +// WeightedOperations returns all the modules' weighted operations of an application +func (mm *Manager) WeightedOperations(state sdkmodule.SimulationState, modules []sdkmodule.AppModuleSimulation) []simulation.WeightedOperation { + wOps := make([]simulation.WeightedOperation, 0, len(modules)+len(mm.weightedOperationsHandlers)) + // adding non ADR-33 modules weighted operations + for _, m := range modules { + wOps = append(wOps, m.WeightedOperations(state)...) + } + + // adding ADR-33 modules weighted operations + for _, weightedOperationHandler := range mm.weightedOperationsHandlers { + wOps = append(wOps, weightedOperationHandler(state)...) + } + + return wOps +} + +// AuthorizationMiddleware is a function that allows for more complex authorization than the default authorization scheme, +// such as delegated permissions. It will be called only if the default authorization fails. +type AuthorizationMiddleware func(ctx sdk.Context, methodName string, req sdk.Msg, signer sdk.AccAddress) bool + +// SetAuthorizationMiddleware sets AuthorizationMiddleware for the Manager. +func (mm *Manager) SetAuthorizationMiddleware(authzFunc AuthorizationMiddleware) { + mm.router.authzMiddleware = authzFunc +} + +// CompleteInitialization should be the last function on the Manager called before the application starts to perform +// any necessary validation and initialization. +func (mm *Manager) CompleteInitialization() error { + for typ := range mm.requiredServices { + if _, found := mm.router.providedServices[typ]; !found { + return fmt.Errorf("initialization error, service %s was required, but not provided", typ) + } + + } + + return nil +} + +// InitGenesis performs init genesis functionality for modules. +// We pass in existing validatorUpdates from the sdk module Manager.InitGenesis. +func (mm *Manager) InitGenesis(ctx sdk.Context, genesisData map[string]json.RawMessage, validatorUpdates []abci.ValidatorUpdate) abci.ResponseInitChain { + res, err := initGenesis(ctx, mm.cdc, genesisData, validatorUpdates, mm.initGenesisHandlers) + if err != nil { + panic(err) + } + return res +} + +func initGenesis(ctx sdk.Context, cdc codec.Codec, + genesisData map[string]json.RawMessage, validatorUpdates []abci.ValidatorUpdate, + initGenesisHandlers map[string]module.InitGenesisHandler) (abci.ResponseInitChain, error) { + for name, initGenesisHandler := range initGenesisHandlers { + if genesisData[name] == nil || initGenesisHandler == nil { + continue + } + moduleValUpdates, err := initGenesisHandler(types.Context{Context: ctx}, cdc, genesisData[name]) + if err != nil { + return abci.ResponseInitChain{}, err + } + + // use these validator updates if provided, the module manager assumes + // only one module will update the validator set + if len(moduleValUpdates) > 0 { + if len(validatorUpdates) > 0 { + return abci.ResponseInitChain{}, errors.New("validator InitGenesis updates already set by a previous module") + } + validatorUpdates = moduleValUpdates + } + } + + return abci.ResponseInitChain{ + Validators: validatorUpdates, + }, nil +} + +// ExportGenesis performs export genesis functionality for modules. +func (mm *Manager) ExportGenesis(ctx sdk.Context) map[string]json.RawMessage { + genesisData, err := exportGenesis(ctx, mm.cdc, mm.exportGenesisHandlers) + if err != nil { + panic(err) + } + + return genesisData +} + +func exportGenesis(ctx sdk.Context, cdc codec.Codec, exportGenesisHandlers map[string]module.ExportGenesisHandler) (map[string]json.RawMessage, error) { + var err error + genesisData := make(map[string]json.RawMessage) + for name, exportGenesisHandler := range exportGenesisHandlers { + if exportGenesisHandler == nil { + continue + } + genesisData[name], err = exportGenesisHandler(types.Context{Context: ctx}, cdc) + if err != nil { + return genesisData, err + } + } + + return genesisData, nil +} + +type RegisterInvariantsHandler func(ir sdk.InvariantRegistry) + +type configurator struct { + sdkmodule.Configurator + msgServer gogogrpc.Server + queryServer gogogrpc.Server + key *rootModuleKey + cdc codec.Codec + requiredServices map[reflect.Type]bool + initGenesisHandler module.InitGenesisHandler + exportGenesisHandler module.ExportGenesisHandler + weightedOperationHandler WeightedOperationsHandler + registerInvariantsHandler RegisterInvariantsHandler +} + +var _ Configurator = &configurator{} + +func (c *configurator) RegisterWeightedOperationsHandler(operationsHandler WeightedOperationsHandler) { + c.weightedOperationHandler = operationsHandler +} + +func (c *configurator) MsgServer() gogogrpc.Server { + return c.msgServer +} + +func (c *configurator) QueryServer() gogogrpc.Server { + return c.queryServer +} + +func (c *configurator) RegisterInvariantsHandler(registry RegisterInvariantsHandler) { + c.registerInvariantsHandler = registry +} + +func (c *configurator) RegisterGenesisHandlers(initGenesisHandler module.InitGenesisHandler, exportGenesisHandler module.ExportGenesisHandler) { + c.initGenesisHandler = initGenesisHandler + c.exportGenesisHandler = exportGenesisHandler +} + +func (c *configurator) ModuleKey() RootModuleKey { + return c.key +} + +func (c *configurator) Marshaler() codec.Codec { + return c.cdc +} + +func (c *configurator) RequireServer(serverInterface interface{}) { + c.requiredServices[reflect.TypeOf(serverInterface)] = true +} + +type WeightedOperationsHandler func(simstate sdkmodule.SimulationState) []simulation.WeightedOperation diff --git a/regen/types/module/server/module.go b/regen/types/module/server/module.go new file mode 100644 index 0000000000..f29a9ceeb7 --- /dev/null +++ b/regen/types/module/server/module.go @@ -0,0 +1,26 @@ +package server + +import ( + "github.com/cosmos/cosmos-sdk/codec" + sdkmodule "github.com/cosmos/cosmos-sdk/types/module" + + "github.com/cosmos/cosmos-sdk/regen/types/module" +) + +// Module is the module type that all server modules must satisfy +type Module interface { + module.TypeModule + + RegisterServices(Configurator) +} + +type Configurator interface { + sdkmodule.Configurator + + ModuleKey() RootModuleKey + Marshaler() codec.Codec + RequireServer(interface{}) + RegisterInvariantsHandler(registry RegisterInvariantsHandler) + RegisterGenesisHandlers(module.InitGenesisHandler, module.ExportGenesisHandler) + RegisterWeightedOperationsHandler(WeightedOperationsHandler) +} diff --git a/regen/types/module/server/module_key.go b/regen/types/module/server/module_key.go new file mode 100644 index 0000000000..56fb8fa8f7 --- /dev/null +++ b/regen/types/module/server/module_key.go @@ -0,0 +1,20 @@ +package server + +import ( + "github.com/cosmos/cosmos-sdk/regen/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type ModuleKey interface { + types.InvokerConn + + ModuleID() types.ModuleID + Address() sdk.AccAddress +} + +type InvokerFactory func(callInfo CallInfo) (types.Invoker, error) + +type CallInfo struct { + Method string + Caller types.ModuleID +} diff --git a/regen/types/module/server/msgs.go b/regen/types/module/server/msgs.go new file mode 100644 index 0000000000..18ac10f60a --- /dev/null +++ b/regen/types/module/server/msgs.go @@ -0,0 +1,50 @@ +package server + +import ( + "fmt" + + "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetMsgs takes a slice of sdk.Msg's and turn them into Any's. +// This is similar to what is in the cosmos-sdk tx builder +// and could eventually be merged in. +func SetMsgs(msgs []sdk.Msg) ([]*types.Any, error) { + anys := make([]*types.Any, len(msgs)) + for i, msg := range msgs { + var err error + anys[i], err = types.NewAnyWithValue(msg) + if err != nil { + return nil, err + } + } + return anys, nil +} + +// GetMsgs takes a slice of Any's and turn them into sdk.Msg's. +// This is similar to what is in the cosmos-sdk sdk.Tx +// and could eventually be merged in. +func GetMsgs(anys []*types.Any) ([]sdk.Msg, error) { + msgs := make([]sdk.Msg, len(anys)) + for i, any := range anys { + cached := any.GetCachedValue() + if cached == nil { + return nil, fmt.Errorf("any cached value is nil, proposal messages must be correctly packed Any values.") + } + msgs[i] = cached.(sdk.Msg) + } + return msgs, nil +} + +func UnpackInterfaces(unpacker types.AnyUnpacker, anys []*types.Any) error { + for _, any := range anys { + var msg sdk.Msg + err := unpacker.UnpackAny(any, &msg) + if err != nil { + return err + } + } + + return nil +} diff --git a/regen/types/module/server/root_module_key.go b/regen/types/module/server/root_module_key.go new file mode 100644 index 0000000000..c61e4374ec --- /dev/null +++ b/regen/types/module/server/root_module_key.go @@ -0,0 +1,68 @@ +package server + +import ( + "context" + "fmt" + + "github.com/cosmos/cosmos-sdk/regen/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + "google.golang.org/grpc" +) + +type RootModuleKey interface { + ModuleKey + sdk.StoreKey + Derive(path []byte) DerivedModuleKey +} + +type rootModuleKey struct { + moduleName string + invokerFactory InvokerFactory +} + +var _ RootModuleKey = &rootModuleKey{} + +func (r *rootModuleKey) Name() string { + return r.moduleName +} + +func (r *rootModuleKey) String() string { + return fmt.Sprintf("rootModuleKey{%p, %s}", r, r.moduleName) +} + +func (r *rootModuleKey) Invoker(methodName string) (types.Invoker, error) { + return r.invokerFactory(CallInfo{ + Method: methodName, + Caller: r.ModuleID(), + }) +} + +func (r *rootModuleKey) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, _ ...grpc.CallOption) error { + invoker, err := r.Invoker(method) + if err != nil { + return err + } + + return invoker(ctx, args, reply) +} + +func (r *rootModuleKey) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("unsupported") +} + +func (r *rootModuleKey) ModuleID() types.ModuleID { + return types.ModuleID{ModuleName: r.moduleName} +} + +func (r *rootModuleKey) Address() sdk.AccAddress { + return r.ModuleID().Address() +} + +func (r *rootModuleKey) Derive(path []byte) DerivedModuleKey { + return DerivedModuleKey{ + moduleName: r.moduleName, + path: path, + invokerFactory: r.invokerFactory, + } +} diff --git a/regen/types/module/server/router.go b/regen/types/module/server/router.go new file mode 100644 index 0000000000..899549470f --- /dev/null +++ b/regen/types/module/server/router.go @@ -0,0 +1,220 @@ +package server + +import ( + "bytes" + "context" + "fmt" + "reflect" + + "github.com/cosmos/cosmos-sdk/baseapp" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + gogogrpc "github.com/gogo/protobuf/grpc" + "github.com/gogo/protobuf/proto" + "google.golang.org/grpc" + + "github.com/cosmos/cosmos-sdk/regen/types" +) + +type handler struct { + f func(ctx context.Context, args, reply interface{}) error + commitWrites bool + moduleName string +} + +type router struct { + handlers map[string]handler + providedServices map[reflect.Type]bool + authzMiddleware AuthorizationMiddleware + msgServiceRouter *baseapp.MsgServiceRouter +} + +type registrar struct { + *router + baseServer gogogrpc.Server + commitWrites bool + moduleName string +} + +var _ gogogrpc.Server = registrar{} + +func (r registrar) RegisterService(sd *grpc.ServiceDesc, ss interface{}) { + r.providedServices[reflect.TypeOf(sd.HandlerType)] = true + + r.baseServer.RegisterService(sd, ss) + + for _, method := range sd.Methods { + fqName := fmt.Sprintf("/%s/%s", sd.ServiceName, method.MethodName) + methodHandler := method.Handler + + var requestTypeName string + + _, _ = methodHandler(nil, context.Background(), func(i interface{}) error { + req, ok := i.(proto.Message) + if !ok { + // We panic here because there is no other alternative and the app cannot be initialized correctly + // this should only happen if there is a problem with code generation in which case the app won't + // work correctly anyway. + panic(fmt.Errorf("can't register request type %T for service method %s", i, fqName)) + } + requestTypeName = TypeURL(req) + return nil + }, noopInterceptor) + + f := func(ctx context.Context, args, reply interface{}) error { + res, err := methodHandler(ss, ctx, func(i interface{}) error { return nil }, + func(ctx context.Context, _ interface{}, _ *grpc.UnaryServerInfo, unaryHandler grpc.UnaryHandler) (resp interface{}, err error) { + return unaryHandler(ctx, args) + }) + if err != nil { + return err + } + + resValue := reflect.ValueOf(res) + if !resValue.IsZero() && reply != nil { + reflect.ValueOf(reply).Elem().Set(resValue.Elem()) + } + return nil + } + r.handlers[requestTypeName] = handler{ + f: f, + commitWrites: r.commitWrites, + moduleName: r.moduleName, + } + } +} + +func (rtr *router) invoker(methodName string, writeCondition func(context.Context, string, sdk.Msg) error) (types.Invoker, error) { + return func(ctx context.Context, request interface{}, response interface{}, opts ...interface{}) error { + req, ok := request.(proto.Message) + if !ok { + return fmt.Errorf("expected proto.Message, got %T for service method %s", request, methodName) + } + + typeURL := TypeURL(req) + handler, found := rtr.handlers[typeURL] + + msg, isMsg := request.(sdk.Msg) + if !found && !isMsg { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, fmt.Sprintf("cannot find method named %s", methodName)) + } + + // cache wrap the multistore so that inter-module writes are atomic + // see https://github.com/cosmos/cosmos-sdk/issues/8030 + regenCtx := types.UnwrapSDKContext(ctx) + cacheMs := regenCtx.MultiStore().CacheMultiStore() + ctx = sdk.WrapSDKContext(regenCtx.WithMultiStore(cacheMs)) + + // msg handler + if writeCondition != nil && (handler.commitWrites || isMsg) { + err := msg.ValidateBasic() + if err != nil { + return err + } + + err = writeCondition(ctx, methodName, msg) + if err != nil { + return err + } + + // ADR-033 router + if found { + err = handler.f(ctx, request, response) + if err != nil { + return err + } + } else { + // routing using baseapp.MsgServiceRouter + sdkCtx := sdk.UnwrapSDKContext(ctx) + handler := rtr.msgServiceRouter.HandlerByTypeURL(typeURL) + if handler == nil { + return sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized message route: %s;", typeURL) + } + + _, err = handler(sdkCtx, msg) + if err != nil { + return err + } + } + + // only commit writes if there is no error so that calls are atomic + cacheMs.Write() + } else { + // query handler + err := handler.f(ctx, request, response) + if err != nil { + return err + } + + cacheMs.Write() + } + return nil + + }, nil +} + +func (rtr *router) invokerFactory(moduleName string) InvokerFactory { + return func(callInfo CallInfo) (types.Invoker, error) { + moduleID := callInfo.Caller + if moduleName != moduleID.ModuleName { + return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, + fmt.Sprintf("expected a call from module %s, but module %s is calling", moduleName, moduleID.ModuleName)) + } + + moduleAddr := moduleID.Address() + + writeCondition := func(ctx context.Context, methodName string, msgReq sdk.Msg) error { + signers := msgReq.GetSigners() + if len(signers) != 1 { + return fmt.Errorf("inter module Msg invocation requires a single expected signer (%s), but %s expects multiple signers (%+v), ", moduleAddr, methodName, signers) + } + + signer := signers[0] + + if bytes.Equal(moduleAddr, signer) { + return nil + } + + if rtr.authzMiddleware != nil && rtr.authzMiddleware(sdk.UnwrapSDKContext(ctx), methodName, msgReq, moduleAddr) { + return nil + } + + return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, + fmt.Sprintf("expected %s, got %s", signers[0], moduleAddr)) + } + + return rtr.invoker(callInfo.Method, writeCondition) + } +} + +func (rtr *router) testTxFactory(signers []sdk.AccAddress) InvokerFactory { + signerMap := map[string]bool{} + for _, signer := range signers { + signerMap[signer.String()] = true + } + + return func(callInfo CallInfo) (types.Invoker, error) { + return rtr.invoker(callInfo.Method, func(_ context.Context, _ string, req sdk.Msg) error { + for _, signer := range req.GetSigners() { + if _, found := signerMap[signer.String()]; !found { + return sdkerrors.ErrUnauthorized + } + } + return nil + }) + } +} + +func (rtr *router) testQueryFactory() InvokerFactory { + return func(callInfo CallInfo) (types.Invoker, error) { + return rtr.invoker(callInfo.Method, nil) + } +} + +func TypeURL(req proto.Message) string { + return "/" + proto.MessageName(req) +} + +func noopInterceptor(_ context.Context, _ interface{}, _ *grpc.UnaryServerInfo, _ grpc.UnaryHandler) (interface{}, error) { + return nil, nil +} diff --git a/regen/types/module/server/testutil.go b/regen/types/module/server/testutil.go new file mode 100644 index 0000000000..2cee0f89d6 --- /dev/null +++ b/regen/types/module/server/testutil.go @@ -0,0 +1,180 @@ +package server + +import ( + "context" + "encoding/json" + "fmt" + "testing" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/std" + + "github.com/cosmos/cosmos-sdk/regen/types/testutil" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + "google.golang.org/grpc" + + regentypes "github.com/cosmos/cosmos-sdk/regen/types" + "github.com/cosmos/cosmos-sdk/regen/types/module" +) + +type FixtureFactory struct { + t *testing.T + modules []module.Module + signers []sdk.AccAddress + signersBls []sdk.AccAddress + sksBls []cryptotypes.PrivKey + cdc *codec.ProtoCodec + baseApp *baseapp.BaseApp +} + +func NewFixtureFactory(t *testing.T, numSigners int) *FixtureFactory { + signers, signersBls, sksBls := makeTestAddresses(numSigners) + return &FixtureFactory{ + t: t, + signers: signers, + signersBls: signersBls, + sksBls: sksBls, + // cdc and baseApp are initialized here just for compatibility with legacy modules which don't use ADR 033 + // TODO: remove once all code using this uses ADR 033 module wiring + cdc: codec.NewProtoCodec(types.NewInterfaceRegistry()), + baseApp: baseapp.NewBaseApp("test", log.NewNopLogger(), dbm.NewMemDB(), nil), + } +} + +func (ff *FixtureFactory) SetModules(modules []module.Module) { + ff.modules = modules +} + +// Codec is exposed just for compatibility of these test suites with legacy modules and can be removed when everything +// has been migrated to ADR 033 +func (ff *FixtureFactory) Codec() *codec.ProtoCodec { + return ff.cdc +} + +// BaseApp is exposed just for compatibility of these test suites with legacy modules and can be removed when everything +// has been migrated to ADR 033 +func (ff *FixtureFactory) BaseApp() *baseapp.BaseApp { + return ff.baseApp +} + +func makeTestAddresses(count int) ([]sdk.AccAddress, []sdk.AccAddress, []cryptotypes.PrivKey) { + addrs := make([]sdk.AccAddress, count) + for i := 0; i < count; i++ { + _, _, addrs[i] = testdata.KeyTestPubAddr() + } + + addrsBls := make([]sdk.AccAddress, count) + sksBls := make([]cryptotypes.PrivKey, count) + for i := 0; i < count; i++ { + sksBls[i], _, addrsBls[i] = testdata.KeyTestPubAddrBls12381() + } + return addrs, addrsBls, sksBls +} + +func (ff FixtureFactory) Setup() testutil.Fixture { + cdc := ff.cdc + registry := cdc.InterfaceRegistry() + baseApp := ff.baseApp + baseApp.MsgServiceRouter().SetInterfaceRegistry(registry) + baseApp.GRPCQueryRouter().SetInterfaceRegistry(registry) + mm := NewManager(baseApp, cdc) + err := mm.RegisterModules(ff.modules) + require.NoError(ff.t, err) + err = mm.CompleteInitialization() + require.NoError(ff.t, err) + err = baseApp.LoadLatestVersion() + require.NoError(ff.t, err) + + std.RegisterInterfaces(registry) + + return fixture{ + baseApp: baseApp, + router: mm.router, + cdc: cdc, + initGenesisHandlers: mm.initGenesisHandlers, + exportGenesisHandlers: mm.exportGenesisHandlers, + t: ff.t, + signers: ff.signers, + signersBls: ff.signersBls, + sksBls: ff.sksBls, + } +} + +type fixture struct { + baseApp *baseapp.BaseApp + router *router + cdc *codec.ProtoCodec + initGenesisHandlers map[string]module.InitGenesisHandler + exportGenesisHandlers map[string]module.ExportGenesisHandler + t *testing.T + signers []sdk.AccAddress + signersBls []sdk.AccAddress + sksBls []cryptotypes.PrivKey +} + +func (f fixture) Context() context.Context { + return regentypes.Context{Context: f.baseApp.NewUncachedContext(false, tmproto.Header{})} +} + +func (f fixture) TxConn() grpc.ClientConnInterface { + return testKey{invokerFactory: f.router.testTxFactory(append(f.signers, f.signersBls...))} +} + +func (f fixture) QueryConn() grpc.ClientConnInterface { + return testKey{invokerFactory: f.router.testQueryFactory()} +} + +func (f fixture) Signers() []sdk.AccAddress { + return f.signers +} + +func (f fixture) SignersBls() []sdk.AccAddress { + return f.signersBls +} + +func (f fixture) SksBls() []cryptotypes.PrivKey { + return f.sksBls +} + +func (f fixture) InitGenesis(ctx sdk.Context, genesisData map[string]json.RawMessage) (abci.ResponseInitChain, error) { + return initGenesis(ctx, f.cdc, genesisData, []abci.ValidatorUpdate{}, f.initGenesisHandlers) +} + +func (f fixture) ExportGenesis(ctx sdk.Context) (map[string]json.RawMessage, error) { + return exportGenesis(ctx, f.cdc, f.exportGenesisHandlers) +} + +func (f fixture) Codec() *codec.ProtoCodec { + return f.cdc +} + +func (f fixture) Teardown() {} + +type testKey struct { + invokerFactory InvokerFactory +} + +var _ grpc.ClientConnInterface = testKey{} + +func (t testKey) Invoke(ctx context.Context, method string, args interface{}, reply interface{}, _ ...grpc.CallOption) error { + invoker, err := t.invokerFactory(CallInfo{Method: method}) + if err != nil { + return err + } + + return invoker(ctx, args, reply) +} + +func (t testKey) NewStream(context.Context, *grpc.StreamDesc, string, ...grpc.CallOption) (grpc.ClientStream, error) { + return nil, fmt.Errorf("unsupported") +} diff --git a/regen/types/testutil/cli/cmd.go b/regen/types/testutil/cli/cmd.go new file mode 100644 index 0000000000..1f09ae9296 --- /dev/null +++ b/regen/types/testutil/cli/cmd.go @@ -0,0 +1,27 @@ +package cli + +import ( + "context" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/testutil" +) + +// ExecTestCLICmd builds the client context, mocks the output and executes the command. +func ExecTestCLICmd(clientCtx client.Context, cmd *cobra.Command, extraArgs []string) (testutil.BufferWriter, error) { + cmd.SetArgs(extraArgs) + + _, out := testutil.ApplyMockIO(cmd) + clientCtx = clientCtx.WithOutput(out) + + ctx := context.Background() + ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) + + if err := cmd.ExecuteContext(ctx); err != nil { + return out, err + } + + return out, nil +} diff --git a/regen/types/testutil/fixture.go b/regen/types/testutil/fixture.go new file mode 100644 index 0000000000..832e6b9834 --- /dev/null +++ b/regen/types/testutil/fixture.go @@ -0,0 +1,63 @@ +/*Package server defines fixture interfaces and implementations for testing +server implementations with multiple backends. + +Currently one backend - an in-memory store with no ABCI application is supported +in configuration.Fixture. + +A multi-node in-process ABCI-based backend for full integration tests is planned +based on to the Cosmos SDK in-process integration test framework. +*/ +package testutil + +import ( + "context" + "encoding/json" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" + "google.golang.org/grpc" +) + +// FixtureFactory defines an interface for creating server test fixtures +type FixtureFactory interface { + + // Setup runs necessary fixture setup and returns a fresh Fixture environment. + Setup() Fixture +} + +// Fixture defines an interface for interacting with app services in tests +// independent of the backend. +type Fixture interface { + + // Context is the context.Context to be used with gRPC generated client code. + Context() context.Context + + // TxConn is the grpc.ClientConnInterface to be used when constructing Msg service clients. + TxConn() grpc.ClientConnInterface + + // QueryConn is the grpc.ClientConnInterface to be used when constructing Query service clients. + QueryConn() grpc.ClientConnInterface + + // Signers are a list of addresses which can be used to sign transactions. They may either be + // random or correspond to nodes in a test network which have keyrings. + Signers() []sdk.AccAddress + + SignersBls() []sdk.AccAddress + + SksBls() []cryptotypes.PrivKey + + // InitGenesis initializes genesis for all modules with provided genesisData. + InitGenesis(ctx sdk.Context, genesisData map[string]json.RawMessage) (abci.ResponseInitChain, error) + + // ExportGenesis returns raw encoded JSON genesis state for all modules. + ExportGenesis(ctx sdk.Context) (map[string]json.RawMessage, error) + + // Codec is the app ProtoCodec. + Codec() *codec.ProtoCodec + + // Teardown performs any teardown actions for the fixture. + Teardown() +} diff --git a/regen/types/testutil/network/doc.go b/regen/types/testutil/network/doc.go new file mode 100644 index 0000000000..9e44f371ab --- /dev/null +++ b/regen/types/testutil/network/doc.go @@ -0,0 +1,65 @@ +/* +Package network implements and exposes a fully operational in-process Tendermint +test network that consists of at least one or potentially many validators. This +test network can be used primarily for integration tests or unit test suites. + +The test network utilizes SimApp as the ABCI application and uses all the modules +defined in the Cosmos SDK. An in-process test network can be configured with any +number of validators as well as account funds and even custom genesis state. + +When creating a test network, a series of Validator objects are returned. Each +Validator object has useful information such as their address and public key. A +Validator will also provide its RPC, P2P, and API addresses that can be useful +for integration testing. In addition, a Tendermint local RPC client is also provided +which can be handy for making direct RPC calls to Tendermint. + +Note, due to limitations in concurrency and the design of the RPC layer in +Tendermint, only the first Validator object will have an RPC and API client +exposed. Due to this exact same limitation, only a single test network can exist +at a time. A caller must be certain it calls Cleanup after it no longer needs +the network. + +A typical testing flow might look like the following: + + type IntegrationTestSuite struct { + suite.Suite + + cfg testutil.Config + network *testutil.Network + } + + func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + cfg := testutil.DefaultConfig() + cfg.NumValidators = 1 + + s.cfg = cfg + s.network = testutil.New(s.T(), cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) + } + + func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + + // This is important and must be called to ensure other tests can create + // a network! + s.network.Cleanup() + } + + func (s *IntegrationTestSuite) TestQueryBalancesRequestHandlerFn() { + val := s.network.Validators[0] + baseURL := val.APIAddress + + // Use baseURL to make API HTTP requests or use val.RPCClient to make direct + // Tendermint RPC calls. + // ... + } + + func TestIntegrationTestSuite(t *testing.T) { + suite.Run(t, new(IntegrationTestSuite)) + } +*/ +package network diff --git a/regen/types/testutil/network/network.go b/regen/types/testutil/network/network.go new file mode 100644 index 0000000000..5a514b5075 --- /dev/null +++ b/regen/types/testutil/network/network.go @@ -0,0 +1,479 @@ +package network + +import ( + "bufio" + "context" + "encoding/json" + "errors" + "fmt" + "io/ioutil" + "net/url" + "os" + "path/filepath" + "sync" + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/simapp/params" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + tmrand "github.com/tendermint/tendermint/libs/rand" + dbm "github.com/tendermint/tm-db" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/server" + "github.com/cosmos/cosmos-sdk/server/api" + srvconfig "github.com/cosmos/cosmos-sdk/server/config" + servertypes "github.com/cosmos/cosmos-sdk/server/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" + tmcfg "github.com/tendermint/tendermint/config" + tmflags "github.com/tendermint/tendermint/libs/cli/flags" + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/node" + tmclient "github.com/tendermint/tendermint/rpc/client" + "google.golang.org/grpc" +) + +// package-wide network lock to only allow one test network at a time +var lock = new(sync.Mutex) + +// AppConstructor defines a function which accepts a network configuration and +// creates an ABCI Application to provide to Tendermint. +type AppConstructor = func(val Validator) servertypes.Application + +// NewAppConstructor returns a new simapp AppConstructor +func NewAppConstructor(encodingCfg params.EncodingConfig) AppConstructor { + return func(val Validator) servertypes.Application { + return simapp.NewSimApp( + val.Ctx.Logger, dbm.NewMemDB(), nil, true, make(map[int64]bool), val.Ctx.Config.RootDir, 0, + encodingCfg, + simapp.EmptyAppOptions{}, + baseapp.SetPruning(storetypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), + baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), + ) + } +} + +// Config defines the necessary configuration used to bootstrap and start an +// in-process local testing network. +type Config struct { + Codec codec.Codec + LegacyAmino *codec.LegacyAmino // TODO: Remove! + InterfaceRegistry codectypes.InterfaceRegistry + + TxConfig client.TxConfig + AccountRetriever client.AccountRetriever + AppConstructor AppConstructor // the ABCI application constructor + GenesisState map[string]json.RawMessage // custom gensis state to provide + TimeoutCommit time.Duration // the consensus commitment timeout + ChainID string // the network chain-id + NumValidators int // the total number of validators to create and bond + BondDenom string // the staking bond denomination + MinGasPrices string // the minimum gas prices each validator will accept + AccountTokens sdk.Int // the amount of unique validator tokens (e.g. 1000node0) + StakingTokens sdk.Int // the amount of tokens each validator has available to stake + BondedTokens sdk.Int // the amount of tokens each validator stakes + PruningStrategy string // the pruning strategy each validator will have + EnableLogging bool // enable Tendermint logging to STDOUT + CleanupDir bool // remove base temporary directory during cleanup + SigningAlgo string // signing algorithm for keys + KeyringOptions []keyring.Option +} + +// DefaultConfig returns a sane default configuration suitable for nearly all +// testing requirements. +func DefaultConfig() Config { + encCfg := simapp.MakeTestEncodingConfig() + + return Config{ + Codec: encCfg.Marshaler, + TxConfig: encCfg.TxConfig, + LegacyAmino: encCfg.Amino, + InterfaceRegistry: encCfg.InterfaceRegistry, + AccountRetriever: authtypes.AccountRetriever{}, + AppConstructor: NewAppConstructor(encCfg), + GenesisState: simapp.ModuleBasics.DefaultGenesis(encCfg.Marshaler), + TimeoutCommit: 2 * time.Second, + ChainID: "chain-" + tmrand.NewRand().Str(6), + NumValidators: 4, + BondDenom: sdk.DefaultBondDenom, + MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), + AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction), + StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction), + BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), + PruningStrategy: storetypes.PruningOptionNothing, + CleanupDir: true, + SigningAlgo: string(hd.Secp256k1Type), + KeyringOptions: []keyring.Option{}, + } +} + +type ( + // Network defines a local in-process testing network using SimApp. It can be + // configured to start any number of validators, each with its own RPC and API + // clients. Typically, this test network would be used in client and integration + // testing where user input is expected. + // + // Note, due to Tendermint constraints in regards to RPC functionality, there + // may only be one test network running at a time. Thus, any caller must be + // sure to Cleanup after testing is finished in order to allow other tests + // to create networks. In addition, only the first validator will have a valid + // RPC and API server/client. + Network struct { + T *testing.T + BaseDir string + Validators []*Validator + + Config Config + } + + // Validator defines an in-process Tendermint validator node. Through this object, + // a client can make RPC and API calls and interact with any client command + // or handler. + Validator struct { + AppConfig *srvconfig.Config + ClientCtx client.Context + Ctx *server.Context + Dir string + NodeID string + PubKey cryptotypes.PubKey + Moniker string + APIAddress string + RPCAddress string + P2PAddress string + Address sdk.AccAddress + ValAddress sdk.ValAddress + RPCClient tmclient.Client + + tmNode *node.Node + api *api.Server + grpc *grpc.Server + } +) + +// New creates Network +func New(t *testing.T, cfg Config) *Network { + // only one caller/test can create and use a network at a time + t.Log("acquiring test network lock") + lock.Lock() + + baseDir, err := ioutil.TempDir(t.TempDir(), cfg.ChainID) + require.NoError(t, err) + t.Logf("created temporary directory: %s", baseDir) + + network := &Network{ + T: t, + BaseDir: baseDir, + Validators: make([]*Validator, cfg.NumValidators), + Config: cfg, + } + + t.Log("preparing test network...") + + monikers := make([]string, cfg.NumValidators) + nodeIDs := make([]string, cfg.NumValidators) + valPubKeys := make([]cryptotypes.PubKey, cfg.NumValidators) + + var ( + genAccounts []authtypes.GenesisAccount + genBalances []banktypes.Balance + genFiles []string + ) + + buf := bufio.NewReader(os.Stdin) + + // generate private keys, node IDs, and initial transactions + for i := 0; i < cfg.NumValidators; i++ { + appCfg := srvconfig.DefaultConfig() + appCfg.Pruning = cfg.PruningStrategy + appCfg.MinGasPrices = cfg.MinGasPrices + appCfg.API.Enable = true + appCfg.API.Swagger = false + appCfg.Telemetry.Enabled = false + + ctx := server.NewDefaultContext() + tmCfg := ctx.Config + tmCfg.Consensus.TimeoutCommit = cfg.TimeoutCommit + + // Only allow the first validator to expose an RPC, API and gRPC + // server/client due to Tendermint in-process constraints. + apiAddr := "" + tmCfg.RPC.ListenAddress = "" + appCfg.GRPC.Enable = false + if i == 0 { + apiListenAddr, _, err := server.FreeTCPAddr() + require.NoError(t, err) + appCfg.API.Address = apiListenAddr + + apiURL, err := url.Parse(apiListenAddr) + require.NoError(t, err) + apiAddr = fmt.Sprintf("http://%s:%s", apiURL.Hostname(), apiURL.Port()) + + rpcAddr, _, err := server.FreeTCPAddr() + require.NoError(t, err) + tmCfg.RPC.ListenAddress = rpcAddr + + _, grpcPort, err := server.FreeTCPAddr() + require.NoError(t, err) + appCfg.GRPC.Address = fmt.Sprintf("0.0.0.0:%s", grpcPort) + appCfg.GRPC.Enable = true + } + + logger := log.NewNopLogger() + if cfg.EnableLogging { + logger = log.NewTMLogger(log.NewSyncWriter(os.Stdout)) + logger, _ = tmflags.ParseLogLevel("info", logger, tmcfg.DefaultLogLevel) + } + + ctx.Logger = logger + + nodeDirName := fmt.Sprintf("node%d", i) + nodeDir := filepath.Join(network.BaseDir, nodeDirName, "simd") + clientDir := filepath.Join(network.BaseDir, nodeDirName, "simcli") + gentxsDir := filepath.Join(network.BaseDir, "gentxs") + + require.NoError(t, os.MkdirAll(filepath.Join(nodeDir, "config"), 0755)) + require.NoError(t, os.MkdirAll(clientDir, 0755)) + + tmCfg.SetRoot(nodeDir) + tmCfg.Moniker = nodeDirName + monikers[i] = nodeDirName + + proxyAddr, _, err := server.FreeTCPAddr() + require.NoError(t, err) + tmCfg.ProxyApp = proxyAddr + + p2pAddr, _, err := server.FreeTCPAddr() + require.NoError(t, err) + tmCfg.P2P.ListenAddress = p2pAddr + tmCfg.P2P.AddrBookStrict = false + tmCfg.P2P.AllowDuplicateIP = true + + nodeID, pubKey, err := genutil.InitializeNodeValidatorFiles(tmCfg) + require.NoError(t, err) + nodeIDs[i] = nodeID + valPubKeys[i] = pubKey + + kb, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendTest, clientDir, buf, cfg.KeyringOptions...) + require.NoError(t, err) + + keyringAlgos, _ := kb.SupportedAlgorithms() + algo, err := keyring.NewSigningAlgoFromString(cfg.SigningAlgo, keyringAlgos) + require.NoError(t, err) + + addr, secret, err := server.GenerateSaveCoinKey(kb, nodeDirName, true, algo) + require.NoError(t, err) + + info := map[string]string{"secret": secret} + infoBz, err := json.Marshal(info) + require.NoError(t, err) + + // save private key seed words + require.NoError(t, writeFile(fmt.Sprintf("%v.json", "key_seed"), clientDir, infoBz)) + + balances := sdk.NewCoins( + sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), cfg.AccountTokens), + sdk.NewCoin(cfg.BondDenom, cfg.StakingTokens), + ) + + genFiles = append(genFiles, tmCfg.GenesisFile()) + genBalances = append(genBalances, banktypes.Balance{Address: addr.String(), Coins: balances.Sort()}) + genAccounts = append(genAccounts, authtypes.NewBaseAccount(addr, nil, 0, 0)) + + commission, err := sdk.NewDecFromStr("0.5") + require.NoError(t, err) + + createValMsg, err := stakingtypes.NewMsgCreateValidator( + sdk.ValAddress(addr), + valPubKeys[i], + sdk.NewCoin(sdk.DefaultBondDenom, cfg.BondedTokens), + stakingtypes.NewDescription(nodeDirName, "", "", "", ""), + stakingtypes.NewCommissionRates(commission, sdk.OneDec(), sdk.OneDec()), + sdk.OneInt(), + ) + if err != nil { + panic(err) + } + + p2pURL, err := url.Parse(p2pAddr) + require.NoError(t, err) + + memo := fmt.Sprintf("%s@%s:%s", nodeIDs[i], p2pURL.Hostname(), p2pURL.Port()) + fee := sdk.NewCoins(sdk.NewCoin(fmt.Sprintf("%stoken", nodeDirName), sdk.NewInt(0))) + txBuilder := cfg.TxConfig.NewTxBuilder() + require.NoError(t, txBuilder.SetMsgs(createValMsg)) + txBuilder.SetFeeAmount(fee) // Arbitrary fee + txBuilder.SetGasLimit(1000000) // Need at least 100386 + txBuilder.SetMemo(memo) + + txFactory := tx.Factory{} + txFactory = txFactory. + WithChainID(cfg.ChainID). + WithMemo(memo). + WithKeybase(kb). + WithTxConfig(cfg.TxConfig) + + err = tx.Sign(txFactory, nodeDirName, txBuilder, true) + require.NoError(t, err) + + txBz, err := cfg.TxConfig.TxJSONEncoder()(txBuilder.GetTx()) + require.NoError(t, err) + require.NoError(t, writeFile(fmt.Sprintf("%v.json", nodeDirName), gentxsDir, txBz)) + + srvconfig.WriteConfigFile(filepath.Join(nodeDir, "config/app.toml"), appCfg) + + clientCtx := client.Context{}. + WithKeyring(kb). + WithHomeDir(tmCfg.RootDir). + WithChainID(cfg.ChainID). + WithInterfaceRegistry(cfg.InterfaceRegistry). + WithCodec(cfg.Codec). + WithLegacyAmino(cfg.LegacyAmino). + WithTxConfig(cfg.TxConfig). + WithAccountRetriever(cfg.AccountRetriever) + + network.Validators[i] = &Validator{ + AppConfig: appCfg, + ClientCtx: clientCtx, + Ctx: ctx, + Dir: filepath.Join(network.BaseDir, nodeDirName), + NodeID: nodeID, + PubKey: pubKey, + Moniker: nodeDirName, + RPCAddress: tmCfg.RPC.ListenAddress, + P2PAddress: tmCfg.P2P.ListenAddress, + APIAddress: apiAddr, + Address: addr, + ValAddress: sdk.ValAddress(addr), + } + } + + require.NoError(t, initGenFiles(cfg, genAccounts, genBalances, genFiles)) + require.NoError(t, collectGenFiles(cfg, network.Validators, network.BaseDir)) + + t.Log("starting test network...") + for _, v := range network.Validators { + require.NoError(t, startInProcess(cfg, v)) + } + + t.Log("started test network") + + // Ensure we cleanup incase any test was abruptly halted (e.g. SIGINT) as any + // defer in a test would not be called. + server.TrapSignal(network.Cleanup) + + return network +} + +// LatestHeight returns the latest height of the network or an error if the +// query fails or no validators exist. +func (n *Network) LatestHeight() (int64, error) { + if len(n.Validators) == 0 { + return 0, errors.New("no validators available") + } + + status, err := n.Validators[0].RPCClient.Status(context.Background()) + if err != nil { + return 0, err + } + + return status.SyncInfo.LatestBlockHeight, nil +} + +// WaitForHeight performs a blocking check where it waits for a block to be +// committed after a given block. If that height is not reached within a timeout, +// an error is returned. Regardless, the latest height queried is returned. +func (n *Network) WaitForHeight(h int64) (int64, error) { + return n.WaitForHeightWithTimeout(h, 10*time.Second) +} + +// WaitForHeightWithTimeout is the same as WaitForHeight except the caller can +// provide a custom timeout. +func (n *Network) WaitForHeightWithTimeout(h int64, t time.Duration) (int64, error) { + ticker := time.NewTicker(time.Second) + timeout := time.After(t) + + if len(n.Validators) == 0 { + return 0, errors.New("no validators available") + } + + var latestHeight int64 + val := n.Validators[0] + + for { + select { + case <-timeout: + ticker.Stop() + return latestHeight, errors.New("timeout exceeded waiting for block") + case <-ticker.C: + status, err := val.RPCClient.Status(context.Background()) + if err == nil && status != nil { + latestHeight = status.SyncInfo.LatestBlockHeight + if latestHeight >= h { + return latestHeight, nil + } + } + } + } +} + +// WaitForNextBlock waits for the next block to be committed, returning an error +// upon failure. +func (n *Network) WaitForNextBlock() error { + lastBlock, err := n.LatestHeight() + if err != nil { + return err + } + + _, err = n.WaitForHeight(lastBlock + 1) + if err != nil { + return err + } + + return err +} + +// Cleanup removes the root testing (temporary) directory and stops both the +// Tendermint and API services. It allows other callers to create and start +// test networks. This method must be called when a test is finished, typically +// in a defer. +func (n *Network) Cleanup() { + defer func() { + lock.Unlock() + n.T.Log("released test network lock") + }() + + n.T.Log("cleaning up test network...") + + for _, v := range n.Validators { + if v.tmNode != nil && v.tmNode.IsRunning() { + _ = v.tmNode.Stop() + } + + if v.api != nil { + _ = v.api.Close() + } + + if v.grpc != nil { + v.grpc.Stop() + } + } + + if n.Config.CleanupDir { + _ = os.RemoveAll(n.BaseDir) + } + + n.T.Log("finished cleaning up test network") +} diff --git a/regen/types/testutil/network/suite.go b/regen/types/testutil/network/suite.go new file mode 100644 index 0000000000..8f49791cfc --- /dev/null +++ b/regen/types/testutil/network/suite.go @@ -0,0 +1,38 @@ +package network + +import ( + "time" + + "github.com/stretchr/testify/suite" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg Config + network *Network +} + +func NewIntegrationTestSuite(cfg Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + s.network = New(s.T(), s.cfg) + s.Require().NotNil(s.network) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestNetwork_Liveness() { + h, err := s.network.WaitForHeightWithTimeout(10, time.Minute) + s.Require().NoError(err, "expected to reach 10 blocks; got %d", h) +} diff --git a/regen/types/testutil/network/util.go b/regen/types/testutil/network/util.go new file mode 100644 index 0000000000..7393500802 --- /dev/null +++ b/regen/types/testutil/network/util.go @@ -0,0 +1,190 @@ +package network + +import ( + "encoding/json" + "path/filepath" + "time" + + tmos "github.com/tendermint/tendermint/libs/os" + "github.com/tendermint/tendermint/node" + "github.com/tendermint/tendermint/p2p" + pvm "github.com/tendermint/tendermint/privval" + "github.com/tendermint/tendermint/proxy" + "github.com/tendermint/tendermint/rpc/client/local" + "github.com/tendermint/tendermint/types" + tmtime "github.com/tendermint/tendermint/types/time" + + "github.com/cosmos/cosmos-sdk/server/api" + servergrpc "github.com/cosmos/cosmos-sdk/server/grpc" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" +) + +func startInProcess(cfg Config, val *Validator) error { + logger := val.Ctx.Logger + tmCfg := val.Ctx.Config + tmCfg.Instrumentation.Prometheus = false + + nodeKey, err := p2p.LoadOrGenNodeKey(tmCfg.NodeKeyFile()) + if err != nil { + return err + } + + app := cfg.AppConstructor(*val) + + genDocProvider := node.DefaultGenesisDocProviderFunc(tmCfg) + tmNode, err := node.NewNode( + tmCfg, + pvm.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()), + nodeKey, + proxy.NewLocalClientCreator(app), + genDocProvider, + node.DefaultDBProvider, + node.DefaultMetricsProvider(tmCfg.Instrumentation), + logger.With("module", val.Moniker), + ) + if err != nil { + return err + } + + if err := tmNode.Start(); err != nil { + return err + } + + val.tmNode = tmNode + + if val.RPCAddress != "" { + val.RPCClient = local.New(tmNode) + } + + if val.APIAddress != "" { + val.ClientCtx = val.ClientCtx. + WithClient(val.RPCClient) + + apiSrv := api.New(val.ClientCtx, logger.With("module", "api-server")) + app.RegisterAPIRoutes(apiSrv, val.AppConfig.API) + + errCh := make(chan error) + + go func() { + if err := apiSrv.Start(*val.AppConfig); err != nil { + errCh <- err + } + }() + + select { + case err := <-errCh: + return err + case <-time.After(5 * time.Second): // assume server started successfully + } + + val.api = apiSrv + } + + if val.AppConfig.GRPC.Enable { + grpcSrv, err := servergrpc.StartGRPCServer(val.ClientCtx, app, val.AppConfig.GRPC.Address) + if err != nil { + return err + } + + val.grpc = grpcSrv + } + + return nil +} + +func collectGenFiles(cfg Config, vals []*Validator, outputDir string) error { + genTime := tmtime.Now() + + for i := 0; i < cfg.NumValidators; i++ { + tmCfg := vals[i].Ctx.Config + + nodeDir := filepath.Join(outputDir, vals[i].Moniker, "simd") + gentxsDir := filepath.Join(outputDir, "gentxs") + + tmCfg.Moniker = vals[i].Moniker + tmCfg.SetRoot(nodeDir) + + initCfg := genutiltypes.NewInitConfig(cfg.ChainID, gentxsDir, vals[i].NodeID, vals[i].PubKey) + + genFile := tmCfg.GenesisFile() + genDoc, err := types.GenesisDocFromFile(genFile) + if err != nil { + return err + } + + appState, err := genutil.GenAppStateFromConfig(cfg.Codec, cfg.TxConfig, + tmCfg, initCfg, *genDoc, banktypes.GenesisBalancesIterator{}) + if err != nil { + return err + } + + // overwrite each validator's genesis file to have a canonical genesis time + if err := genutil.ExportGenesisFileWithTime(genFile, cfg.ChainID, nil, appState, genTime); err != nil { + return err + } + } + + return nil +} + +func initGenFiles(cfg Config, genAccounts []authtypes.GenesisAccount, genBalances []banktypes.Balance, genFiles []string) error { + + // set the accounts in the genesis state + var authGenState authtypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &authGenState) + + accounts, err := authtypes.PackAccounts(genAccounts) + if err != nil { + return err + } + + authGenState.Accounts = accounts + cfg.GenesisState[authtypes.ModuleName] = cfg.Codec.MustMarshalJSON(&authGenState) + + // set the balances in the genesis state + var bankGenState banktypes.GenesisState + cfg.Codec.MustUnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &bankGenState) + + bankGenState.Balances = genBalances + cfg.GenesisState[banktypes.ModuleName] = cfg.Codec.MustMarshalJSON(&bankGenState) + + appGenStateJSON, err := json.MarshalIndent(cfg.GenesisState, "", " ") + if err != nil { + return err + } + + genDoc := types.GenesisDoc{ + ChainID: cfg.ChainID, + AppState: appGenStateJSON, + Validators: nil, + } + + // generate empty genesis files for each validator and save + for i := 0; i < cfg.NumValidators; i++ { + if err := genDoc.SaveAs(genFiles[i]); err != nil { + return err + } + } + + return nil +} + +func writeFile(name string, dir string, contents []byte) error { + writePath := filepath.Join(dir) + file := filepath.Join(writePath, name) + + err := tmos.EnsureDir(writePath, 0755) + if err != nil { + return err + } + + err = tmos.WriteFile(file, contents, 0644) + if err != nil { + return err + } + + return nil +} diff --git a/simapp/app.go b/simapp/app.go index e3e73669b8..71393f6ee8 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -7,6 +7,8 @@ import ( "os" "path/filepath" + regenserver "github.com/cosmos/cosmos-sdk/regen/types/module/server" + airdroptypes "github.com/cosmos/cosmos-sdk/x/airdrop/types" "github.com/gorilla/mux" @@ -101,24 +103,26 @@ var ( // non-dependant module elements, such as codec registration // and genesis verification. ModuleBasics = module.NewBasicManager( - auth.AppModuleBasic{}, - genutil.AppModuleBasic{}, - bank.AppModuleBasic{}, - capability.AppModuleBasic{}, - staking.AppModuleBasic{}, - mint.AppModuleBasic{}, - distr.AppModuleBasic{}, - gov.NewAppModuleBasic( - paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, - ), - params.AppModuleBasic{}, - crisis.AppModuleBasic{}, - slashing.AppModuleBasic{}, - feegrantmodule.AppModuleBasic{}, - upgrade.AppModuleBasic{}, - evidence.AppModuleBasic{}, - authzmodule.AppModuleBasic{}, - vesting.AppModuleBasic{}, + append([]module.AppModuleBasic{ + auth.AppModuleBasic{}, + genutil.AppModuleBasic{}, + bank.AppModuleBasic{}, + capability.AppModuleBasic{}, + staking.AppModuleBasic{}, + mint.AppModuleBasic{}, + distr.AppModuleBasic{}, + gov.NewAppModuleBasic( + paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler, + ), + params.AppModuleBasic{}, + crisis.AppModuleBasic{}, + slashing.AppModuleBasic{}, + feegrantmodule.AppModuleBasic{}, + upgrade.AppModuleBasic{}, + evidence.AppModuleBasic{}, + authzmodule.AppModuleBasic{}, + vesting.AppModuleBasic{}, + }, setCustomModuleBasics()...)..., ) // module account permissions @@ -177,6 +181,13 @@ type SimApp struct { // simulation manager sm *module.SimulationManager + // server module manager + // NOTE: We will likely want to make this new manager compatible + // with module.Manager so that we can have existing cosmos-sdk modules + // use ADR 33 approach without the need for removing their keepers + // and a larger refactoring. + smm *regenserver.Manager + // module configurator configurator module.Configurator } @@ -207,12 +218,14 @@ func NewSimApp( bApp.SetInterfaceRegistry(interfaceRegistry) keys := sdk.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, - minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, - evidencetypes.StoreKey, capabilitytypes.StoreKey, - airdroptypes.StoreKey, - authzkeeper.StoreKey, + append([]string{ + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, + evidencetypes.StoreKey, capabilitytypes.StoreKey, + airdroptypes.StoreKey, + authzkeeper.StoreKey, + }, setCustomKVStoreKeys()...)..., ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) // NOTE: The testingkey is just mounted for testing purposes. Actual applications should @@ -287,6 +300,9 @@ func NewSimApp( &stakingKeeper, govRouter, ) + // register custom modules here + app.smm = setCustomModules(app, interfaceRegistry) + app.AirdropKeeper = airdropkeeper.NewKeeper( appCodec, keys[airdroptypes.StoreKey], app.GetSubspace(airdroptypes.ModuleName), app.BankKeeper, authtypes.FeeCollectorName, @@ -313,25 +329,27 @@ func NewSimApp( // NOTE: Any module instantiated in the module manager that is later modified // must be passed by reference here. app.mm = module.NewManager( - genutil.NewAppModule( - app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, - encodingConfig.TxConfig, - ), - auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), - vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), - capability.NewAppModule(appCodec, *app.CapabilityKeeper), - crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), - feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), - gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), - mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), - slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), - upgrade.NewAppModule(app.UpgradeKeeper), - evidence.NewAppModule(app.EvidenceKeeper), - params.NewAppModule(app.ParamsKeeper), - authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + append([]module.AppModule{ + genutil.NewAppModule( + app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, + encodingConfig.TxConfig, + ), + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), + vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), + capability.NewAppModule(appCodec, *app.CapabilityKeeper), + crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), + feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), + mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), + slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), + upgrade.NewAppModule(app.UpgradeKeeper), + evidence.NewAppModule(app.EvidenceKeeper), + params.NewAppModule(app.ParamsKeeper), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + }, app.setCustomModuleManager()...)..., ) // During begin block slashing happens after distr.BeginBlocker so that @@ -351,10 +369,12 @@ func NewSimApp( // so that other modules that want to create or claim capabilities afterwards in InitChain // can do so safely. app.mm.SetOrderInitGenesis( - capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, - slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, - genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, - feegrant.ModuleName, + append([]string{ + capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName, + slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName, + genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName, + feegrant.ModuleName, + }, setCustomOrderInitGenesis()...)..., ) app.mm.RegisterInvariants(&app.CrisisKeeper) @@ -370,18 +390,20 @@ func NewSimApp( // NOTE: this is not required apps that don't use the simulator for fuzz testing // transactions app.sm = module.NewSimulationManager( - auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), - bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), - capability.NewAppModule(appCodec, *app.CapabilityKeeper), - feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), - gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), - mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), - staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), - distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - params.NewAppModule(app.ParamsKeeper), - evidence.NewAppModule(app.EvidenceKeeper), - authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + append([]module.AppModuleSimulation{ + auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts), + bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), + capability.NewAppModule(appCodec, *app.CapabilityKeeper), + feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), + mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), + staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), + distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + params.NewAppModule(app.ParamsKeeper), + evidence.NewAppModule(app.EvidenceKeeper), + authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + }, app.setCustomSimulationManager()...)..., ) app.sm.RegisterStoreDecoders() diff --git a/simapp/appconfig.go b/simapp/appconfig.go new file mode 100644 index 0000000000..d47a0e4c8c --- /dev/null +++ b/simapp/appconfig.go @@ -0,0 +1,64 @@ +package simapp + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + moduletypes "github.com/cosmos/cosmos-sdk/regen/types/module" + regenserver "github.com/cosmos/cosmos-sdk/regen/types/module/server" + + "github.com/cosmos/cosmos-sdk/types/module" + + group "github.com/cosmos/cosmos-sdk/x/group/module" +) + +// from regen-ledger: https://github.com/regen-network/regen-ledger/blob/v2.0.0-beta1/app/experimental_appconfig.go + +func setCustomModuleBasics() []module.AppModuleBasic { + return []module.AppModuleBasic{ + group.Module{}, + } +} + +func setCustomKVStoreKeys() []string { + return []string{} +} + +// setCustomModules registers new modules with the server module manager. +func setCustomModules(app *SimApp, interfaceRegistry types.InterfaceRegistry) *regenserver.Manager { + + /* New Module Wiring START */ + newModuleManager := regenserver.NewManager(app.BaseApp, codec.NewProtoCodec(interfaceRegistry)) + + // BEGIN HACK: this is a total, ugly hack until x/auth & x/bank supports ADR 033 or we have a suitable alternative + groupModule := group.Module{AccountKeeper: app.AccountKeeper, BankKeeper: app.BankKeeper} + // use a separate newModules from the global NewModules here because we need to pass state into the group module + newModules := []moduletypes.Module{ + groupModule, + } + err := newModuleManager.RegisterModules(newModules) + if err != nil { + panic(err) + } + // END HACK + + /* New Module Wiring END */ + return newModuleManager +} + +func (app *SimApp) setCustomModuleManager() []module.AppModule { + return []module.AppModule{} +} + +func setCustomOrderInitGenesis() []string { + return []string{} +} + +func (app *SimApp) setCustomSimulationManager() []module.AppModuleSimulation { + return []module.AppModuleSimulation{ + group.Module{ + Registry: app.interfaceRegistry, + BankKeeper: app.BankKeeper, + AccountKeeper: app.AccountKeeper, + }, + } +} diff --git a/testutil/testdata/tx.go b/testutil/testdata/tx.go index abf3e63c2d..646ac30b49 100644 --- a/testutil/testdata/tx.go +++ b/testutil/testdata/tx.go @@ -3,6 +3,8 @@ package testdata import ( "encoding/json" + "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + "github.com/stretchr/testify/require" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -19,7 +21,7 @@ func KeyTestPubAddr() (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) return key, pub, addr } -// KeyTestPubAddr generates a new secp256r1 keypair. +// KeyTestPubAddrSecp256R1 generates a new secp256r1 keypair. func KeyTestPubAddrSecp256R1(require *require.Assertions) (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) { key, err := secp256r1.GenPrivKey() require.NoError(err) @@ -28,6 +30,14 @@ func KeyTestPubAddrSecp256R1(require *require.Assertions) (cryptotypes.PrivKey, return key, pub, addr } +// KeyTestPubAddrBls12381 generates a new secp256k1 keypair. +func KeyTestPubAddrBls12381() (cryptotypes.PrivKey, cryptotypes.PubKey, sdk.AccAddress) { + key := bls12381.GenPrivKey() + pub := key.PubKey() + addr := sdk.AccAddress(pub.Address()) + return key, pub, addr +} + // NewTestFeeAmount is a test fee amount. func NewTestFeeAmount() sdk.Coins { return sdk.NewCoins(sdk.NewInt64Coin("atom", 150)) @@ -35,7 +45,7 @@ func NewTestFeeAmount() sdk.Coins { // NewTestGasLimit is a test fee gas limit. func NewTestGasLimit() uint64 { - return 120000 + return 150000 } // NewTestMsg creates a message for testing with the given signers. diff --git a/x/auth/ante/ante_test.go b/x/auth/ante/ante_test.go index 7c31c5f460..5d96cef489 100644 --- a/x/auth/ante/ante_test.go +++ b/x/auth/ante/ante_test.go @@ -573,7 +573,7 @@ func (suite *AnteTestSuite) TestAnteHandlerMemoGas() { "tx with memo has enough gas", func() { feeAmount = sdk.NewCoins(sdk.NewInt64Coin("atom", 0)) - gasLimit = 50000 + gasLimit = 60000 suite.txBuilder.SetMemo(strings.Repeat("0123456789", 10)) }, false, diff --git a/x/auth/ante/sigverify.go b/x/auth/ante/sigverify.go index 6dd0d249ad..42d222ef28 100644 --- a/x/auth/ante/sigverify.go +++ b/x/auth/ante/sigverify.go @@ -347,8 +347,11 @@ func (spvd SetPopValidDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate switch pk.(type) { case *bls12381.PubKey, *secp256k1.PubKey, *ed25519.PubKey: - if err := acc.SetPopValid(true); err != nil { - return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPop, err.Error()) + if !acc.GetPopValid() { + if err := acc.SetPopValid(true); err != nil { + return ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidPop, err.Error()) + } + spvd.ak.SetAccount(ctx, acc) } } } diff --git a/x/group/client/client_test.go b/x/group/client/client_test.go new file mode 100644 index 0000000000..d042c25736 --- /dev/null +++ b/x/group/client/client_test.go @@ -0,0 +1,14 @@ +package client_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/regen/types/testutil/network" + "github.com/cosmos/cosmos-sdk/x/group/client/testsuite" + "github.com/stretchr/testify/suite" +) + +func TestIntegrationTestSuite(t *testing.T) { + cfg := network.DefaultConfig() + suite.Run(t, testsuite.NewIntegrationTestSuite(cfg)) +} diff --git a/x/group/client/query.go b/x/group/client/query.go new file mode 100644 index 0000000000..e92475ab44 --- /dev/null +++ b/x/group/client/query.go @@ -0,0 +1,671 @@ +package client + +import ( + "strconv" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/spf13/cobra" +) + +// QueryCmd returns the cli query commands for the group module. +func QueryCmd(name string) *cobra.Command { + queryCmd := &cobra.Command{ + Use: name, + Short: "Querying commands for the group module", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + queryCmd.AddCommand( + QueryGroupInfoCmd(), + QueryGroupAccountInfoCmd(), + QueryGroupMembersCmd(), + QueryGroupsByAdminCmd(), + QueryGroupAccountsByGroupCmd(), + QueryGroupAccountsByAdminCmd(), + QueryProposalCmd(), + QueryProposalsByGroupAccountCmd(), + QueryVoteByProposalVoterCmd(), + QueryVotesByProposalCmd(), + QueryVotesByVoterCmd(), + QueryPollCmd(), + QueryPollsByGroupCmd(), + QueryPollsByCreatorCmd(), + QueryVoteForPollByPollVoterCmd(), + QueryVotesForPollByPollCmd(), + QueryVotesForPollByVoterCmd(), + ) + + return queryCmd +} + +// QueryGroupInfoCmd creates a CLI command for Query/GroupInfo. +func QueryGroupInfoCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "group-info [id]", + Short: "Query for group info by group id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.GroupInfo(cmd.Context(), &group.QueryGroupInfoRequest{ + GroupId: groupID, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res.Info) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryGroupAccountInfoCmd creates a CLI command for Query/GroupAccountInfo. +func QueryGroupAccountInfoCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "group-account-info [group-account]", + Short: "Query for group account info by group account address", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.GroupAccountInfo(cmd.Context(), &group.QueryGroupAccountInfoRequest{ + Address: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res.Info) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryGroupMembersCmd creates a CLI command for Query/GroupMembers. +func QueryGroupMembersCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "group-members [id]", + Short: "Query for group members by group id with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.GroupMembers(cmd.Context(), &group.QueryGroupMembersRequest{ + GroupId: groupID, + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryGroupsByAdminCmd creates a CLI command for Query/GroupsByAdmin. +func QueryGroupsByAdminCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "groups-by-admin [admin]", + Short: "Query for groups by admin account address with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.GroupsByAdmin(cmd.Context(), &group.QueryGroupsByAdminRequest{ + Admin: args[0], + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryGroupAccountsByGroupCmd creates a CLI command for Query/GroupAccountsByGroup. +func QueryGroupAccountsByGroupCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "group-accounts-by-group [group-id]", + Short: "Query for group accounts by group id with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.GroupAccountsByGroup(cmd.Context(), &group.QueryGroupAccountsByGroupRequest{ + GroupId: groupID, + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryGroupAccountsByAdminCmd creates a CLI command for Query/GroupAccountsByAdmin. +func QueryGroupAccountsByAdminCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "group-accounts-by-admin [admin]", + Short: "Query for group accounts by admin account address with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.GroupAccountsByAdmin(cmd.Context(), &group.QueryGroupAccountsByAdminRequest{ + Admin: args[0], + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryProposalCmd creates a CLI command for Query/Proposal. +func QueryProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "proposal [id]", + Short: "Query for proposal by id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.Proposal(cmd.Context(), &group.QueryProposalRequest{ + ProposalId: proposalID, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryProposalsByGroupAccountCmd creates a CLI command for Query/ProposalsByGroupAccount. +func QueryProposalsByGroupAccountCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "proposals-by-group-account [group-account]", + Short: "Query for proposals by group account address with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.ProposalsByGroupAccount(cmd.Context(), &group.QueryProposalsByGroupAccountRequest{ + Address: args[0], + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryVoteByProposalVoterCmd creates a CLI command for Query/VoteByProposalVoter. +func QueryVoteByProposalVoterCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote [proposal-id] [voter]", + Short: "Query for vote by proposal id and voter account address", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.VoteByProposalVoter(cmd.Context(), &group.QueryVoteByProposalVoterRequest{ + ProposalId: proposalID, + Voter: args[1], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryVotesByProposalCmd creates a CLI command for Query/VotesByProposal. +func QueryVotesByProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "votes-by-proposal [proposal-id]", + Short: "Query for votes by proposal id with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.VotesByProposal(cmd.Context(), &group.QueryVotesByProposalRequest{ + ProposalId: proposalID, + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryVotesByVoterCmd creates a CLI command for Query/VotesByVoter. +func QueryVotesByVoterCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "votes-by-voter [voter]", + Short: "Query for votes by voter account address with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.VotesByVoter(cmd.Context(), &group.QueryVotesByVoterRequest{ + Voter: args[0], + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryPollCmd creates a CLI command for Query/Poll. +func QueryPollCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "poll [id]", + Short: "Query for poll by id", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pollID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.Poll(cmd.Context(), &group.QueryPollRequest{ + PollId: pollID, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryPollsByGroupCmd creates a CLI command for Query/PollsByGroup. +func QueryPollsByGroupCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "polls-by-group [group-id]", + Short: "Query for polls by group id with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.PollsByGroup(cmd.Context(), &group.QueryPollsByGroupRequest{ + GroupId: groupID, + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryPollsByCreatorCmd creates a CLI command for Query/PollsByCreator. +func QueryPollsByCreatorCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "polls-by-group [creator]", + Short: "Query for polls by creator address with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.PollsByCreator(cmd.Context(), &group.QueryPollsByCreatorRequest{ + Creator: args[0], + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryVoteForPollByPollVoterCmd creates a CLI command for Query/VoteForPollByPollVoter. +func QueryVoteForPollByPollVoterCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-poll [poll-id] [voter]", + Short: "Query for vote by poll id and voter account address", + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pollID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.VoteForPollByPollVoter(cmd.Context(), &group.QueryVoteForPollByPollVoterRequest{ + PollId: pollID, + Voter: args[1], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryVotesForPollByPollCmd creates a CLI command for Query/VotesByProposal. +func QueryVotesForPollByPollCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "votes-by-poll [poll-id]", + Short: "Query for votes by poll id with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pollID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.VotesForPollByPoll(cmd.Context(), &group.QueryVotesForPollByPollRequest{ + PollId: pollID, + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} + +// QueryVotesForPollByVoterCmd creates a CLI command for Query/VotesForPollByVoter. +func QueryVotesForPollByVoterCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "votes-poll-by-voter [voter]", + Short: "Query for votes by voter account address with pagination flags", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := group.NewQueryClient(clientCtx) + + res, err := queryClient.VotesForPollByVoter(cmd.Context(), &group.QueryVotesForPollByVoterRequest{ + Voter: args[0], + Pagination: pageReq, + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/group/client/testsuite/query.go b/x/group/client/testsuite/query.go new file mode 100644 index 0000000000..4475f45cdc --- /dev/null +++ b/x/group/client/testsuite/query.go @@ -0,0 +1,969 @@ +package testsuite + +import ( + "fmt" + "strconv" + + "github.com/cosmos/cosmos-sdk/regen/types/testutil/cli" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/client" + tmcli "github.com/tendermint/tendermint/libs/cli" +) + +func (s *IntegrationTestSuite) TestQueryGroupInfo() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + }{ + { + "group not found", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "not found: invalid request", + 0, + }, + { + "group id invalid", + []string{"", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + }, + { + "group found", + []string{strconv.FormatUint(s.group.GroupId, 10), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryGroupInfoCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var g group.GroupInfo + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &g)) + s.Require().Equal(s.group.GroupId, g.GroupId) + s.Require().Equal(s.group.Admin, g.Admin) + s.Require().Equal(s.group.TotalWeight, g.TotalWeight) + s.Require().Equal(s.group.Metadata, g.Metadata) + s.Require().Equal(s.group.Version, g.Version) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGroupMembers() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectMembers []*group.GroupMember + }{ + { + "no group", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupMember{}, + }, + { + "members found", + []string{strconv.FormatUint(s.group.GroupId, 10), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupMember{ + { + GroupId: s.group.GroupId, + Member: &group.Member{ + Address: val.Address.String(), + Weight: "3", + Metadata: []byte{1}, + }, + }, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryGroupMembersCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryGroupMembersResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectMembers), len(res.Members)) + for i := range res.Members { + s.Require().Equal(tc.expectMembers[i].GroupId, res.Members[i].GroupId) + s.Require().Equal(tc.expectMembers[i].Member.Address, res.Members[i].Member.Address) + s.Require().Equal(tc.expectMembers[i].Member.Metadata, res.Members[i].Member.Metadata) + s.Require().Equal(tc.expectMembers[i].Member.Weight, res.Members[i].Member.Weight) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGroupsByAdmin() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectGroups []*group.GroupInfo + }{ + { + "invalid admin address", + []string{"invalid"}, + true, + "decoding bech32 failed: invalid bech32 string", + 0, + []*group.GroupInfo{}, + }, + { + "no group", + []string{s.network.Validators[1].Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupInfo{}, + }, + { + "found groups", + []string{val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupInfo{ + s.group, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryGroupsByAdminCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryGroupsByAdminResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectGroups), len(res.Groups)) + for i := range res.Groups { + s.Require().Equal(tc.expectGroups[i].GroupId, res.Groups[i].GroupId) + s.Require().Equal(tc.expectGroups[i].Metadata, res.Groups[i].Metadata) + s.Require().Equal(tc.expectGroups[i].Version, res.Groups[i].Version) + s.Require().Equal(tc.expectGroups[i].TotalWeight, res.Groups[i].TotalWeight) + s.Require().Equal(tc.expectGroups[i].Admin, res.Groups[i].Admin) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGroupAccountInfo() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + }{ + { + "invalid account address", + []string{"invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "decoding bech32 failed: invalid bech32", + 0, + }, + { + "group account not found", + []string{val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "not found: invalid request", + 0, + }, + { + "group account found", + []string{s.groupAccounts[0].Address, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryGroupAccountInfoCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var g group.GroupAccountInfo + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &g)) + s.Require().Equal(s.groupAccounts[0].GroupId, g.GroupId) + s.Require().Equal(s.groupAccounts[0].Address, g.Address) + s.Require().Equal(s.groupAccounts[0].Admin, g.Admin) + s.Require().Equal(s.groupAccounts[0].Metadata, g.Metadata) + s.Require().Equal(s.groupAccounts[0].Version, g.Version) + s.Require().Equal(s.groupAccounts[0].GetDecisionPolicy(), g.GetDecisionPolicy()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGroupAccountsByGroup() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectGroupAccounts []*group.GroupAccountInfo + }{ + { + "invalid group id", + []string{""}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + []*group.GroupAccountInfo{}, + }, + { + "no group account", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupAccountInfo{}, + }, + { + "found group accounts", + []string{strconv.FormatUint(s.group.GroupId, 10), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupAccountInfo{ + s.groupAccounts[0], + s.groupAccounts[1], + s.groupAccounts[2], + s.groupAccounts[3], + s.groupAccounts[4], + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryGroupAccountsByGroupCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryGroupAccountsByGroupResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectGroupAccounts), len(res.GroupAccounts)) + for i := range res.GroupAccounts { + s.Require().Equal(tc.expectGroupAccounts[i].GroupId, res.GroupAccounts[i].GroupId) + s.Require().Equal(tc.expectGroupAccounts[i].Metadata, res.GroupAccounts[i].Metadata) + s.Require().Equal(tc.expectGroupAccounts[i].Version, res.GroupAccounts[i].Version) + s.Require().Equal(tc.expectGroupAccounts[i].Admin, res.GroupAccounts[i].Admin) + s.Require().Equal(tc.expectGroupAccounts[i].GetDecisionPolicy(), res.GroupAccounts[i].GetDecisionPolicy()) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryGroupAccountsByAdmin() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectGroupAccounts []*group.GroupAccountInfo + }{ + { + "invalid admin address", + []string{"invalid"}, + true, + "decoding bech32 failed: invalid bech32 string", + 0, + []*group.GroupAccountInfo{}, + }, + { + "no group account", + []string{s.network.Validators[1].Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupAccountInfo{}, + }, + { + "found group accounts", + []string{val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.GroupAccountInfo{ + s.groupAccounts[0], + s.groupAccounts[1], + s.groupAccounts[2], + s.groupAccounts[3], + s.groupAccounts[4], + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryGroupAccountsByAdminCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryGroupAccountsByAdminResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectGroupAccounts), len(res.GroupAccounts)) + for i := range res.GroupAccounts { + s.Require().Equal(tc.expectGroupAccounts[i].GroupId, res.GroupAccounts[i].GroupId) + s.Require().Equal(tc.expectGroupAccounts[i].Metadata, res.GroupAccounts[i].Metadata) + s.Require().Equal(tc.expectGroupAccounts[i].Version, res.GroupAccounts[i].Version) + s.Require().Equal(tc.expectGroupAccounts[i].Admin, res.GroupAccounts[i].Admin) + s.Require().Equal(tc.expectGroupAccounts[i].GetDecisionPolicy(), res.GroupAccounts[i].GetDecisionPolicy()) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryProposal() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + }{ + { + "not found", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "not found", + 0, + }, + { + "invalid proposal id", + []string{"", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryProposalCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryProposalsByGroupAccount() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectProposals []*group.Proposal + }{ + { + "invalid group account address", + []string{"invalid"}, + true, + "decoding bech32 failed: invalid bech32 string", + 0, + []*group.Proposal{}, + }, + { + "no group account", + []string{s.network.Validators[1].Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.Proposal{}, + }, + { + "found proposals", + []string{s.groupAccounts[0].Address, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.Proposal{ + s.proposal, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryProposalsByGroupAccountCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryProposalsByGroupAccountResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectProposals), len(res.Proposals)) + for i := range res.Proposals { + s.Require().Equal(tc.expectProposals[i], res.Proposals[i]) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryVoteByProposalVoter() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + }{ + { + "invalid voter address", + []string{"1", "invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "decoding bech32 failed: invalid bech32", + 0, + }, + { + "invalid proposal id", + []string{"", val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryVoteByProposalVoterCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryVotesByProposal() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectVotes []*group.Vote + }{ + { + "invalid proposal id", + []string{"", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + []*group.Vote{}, + }, + { + "no votes", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.Vote{}, + }, + { + "found votes", + []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.Vote{ + s.vote, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryVotesByProposalCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryVotesByProposalResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectVotes), len(res.Votes)) + for i := range res.Votes { + s.Require().Equal(tc.expectVotes[i], res.Votes[i]) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryVotesByVoter() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectVotes []*group.Vote + }{ + { + "invalid voter address", + []string{"abcd", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "decoding bech32 failed: invalid bech32", + 0, + []*group.Vote{}, + }, + { + "no votes", + []string{s.groupAccounts[0].Address, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "", + 0, + []*group.Vote{}, + }, + { + "found votes", + []string{val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.Vote{ + s.vote, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryVotesByVoterCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryVotesByVoterResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectVotes), len(res.Votes)) + for i := range res.Votes { + s.Require().Equal(tc.expectVotes[i], res.Votes[i]) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryPoll() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + }{ + { + "not found", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "not found", + 0, + }, + { + "invalid poll id", + []string{"", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryPollCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryPollsByGroup() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectPolls []*group.Poll + }{ + { + "invalid group id", + []string{"abcd", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "invalid syntax", + 0, + []*group.Poll{}, + }, + { + "not found", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "", + 0, + []*group.Poll{}, + }, + { + "found polls", + []string{fmt.Sprintf("%d", s.pollBls.GroupId), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.Poll{ + s.pollBls, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryPollsByGroupCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryPollsByGroupResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectPolls), len(res.Polls)) + for i := range res.Polls { + s.Require().Equal(tc.expectPolls[i], res.Polls[i]) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryVoteForPollByPollVoter() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + aliceInfo, err := clientCtx.Keyring.Key("alice") + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + }{ + { + "all good", + []string{"1", aliceAddr.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + }, + { + "invalid voter address", + []string{"1", "invalid", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "decoding bech32 failed: invalid bech32", + 0, + }, + { + "invalid poll id", + []string{"", aliceAddr.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryVoteForPollByPollVoterCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryVotesForPollByPoll() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectVotes []*group.VotePoll + }{ + { + "invalid proposal id", + []string{"", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + 0, + []*group.VotePoll{}, + }, + { + "no votes", + []string{"12345", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.VotePoll{}, + }, + { + "found votes", + []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.VotePoll{ + s.votePoll, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryVotesForPollByPollCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryVotesForPollByPollResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectVotes), len(res.Votes)) + for i := range res.Votes { + s.Require().Equal(tc.expectVotes[i], res.Votes[i]) + } + } + }) + } +} + +func (s *IntegrationTestSuite) TestQueryVotesForPollByVoter() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + aliceInfo, err := clientCtx.Keyring.Key("alice") + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + expectedCode uint32 + expectVotes []*group.VotePoll + }{ + { + "invalid voter address", + []string{"abcd", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "decoding bech32 failed: invalid bech32", + 0, + []*group.VotePoll{}, + }, + { + "no votes", + []string{s.groupAccounts[0].Address, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + true, + "", + 0, + []*group.VotePoll{}, + }, + { + "found votes", + []string{aliceAddr.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}, + false, + "", + 0, + []*group.VotePoll{ + s.votePoll, + }, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.QueryVotesForPollByVoterCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + + var res group.QueryVotesForPollByVoterResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(tc.expectVotes), len(res.Votes)) + for i := range res.Votes { + s.Require().Equal(tc.expectVotes[i], res.Votes[i]) + } + } + }) + } +} diff --git a/x/group/client/testsuite/tx.go b/x/group/client/testsuite/tx.go new file mode 100644 index 0000000000..819e32a4ed --- /dev/null +++ b/x/group/client/testsuite/tx.go @@ -0,0 +1,2481 @@ +package testsuite + +import ( + "fmt" + "strconv" + "strings" + "time" + + gogotypes "github.com/gogo/protobuf/types" + + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/testutil" + banktestutil "github.com/cosmos/cosmos-sdk/x/bank/client/testutil" + "github.com/gogo/protobuf/proto" + + "github.com/cosmos/cosmos-sdk/regen/types/testutil/cli" + "github.com/cosmos/cosmos-sdk/regen/types/testutil/network" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/client" + "github.com/stretchr/testify/suite" +) + +type IntegrationTestSuite struct { + suite.Suite + + cfg network.Config + network *network.Network + + group *group.GroupInfo + groupAccounts []*group.GroupAccountInfo + + groupBls *group.GroupInfo + groupAccountsBls []*group.GroupAccountInfo + + proposal *group.Proposal + vote *group.Vote + + proposalBls *group.Proposal + pollBls *group.Poll + votePoll *group.VotePoll +} + +const validMetadata = "AQ==" + +func NewIntegrationTestSuite(cfg network.Config) *IntegrationTestSuite { + return &IntegrationTestSuite{cfg: cfg} +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.T().Log("setting up integration test suite") + + // We execute NewIntegrationTestSuite to set cfg field of IntegrationTestSuite + s.cfg.NumValidators = 2 + s.network = network.New(s.T(), s.cfg) + + _, err := s.network.WaitForHeight(1) + s.Require().NoError(err) + + val := s.network.Validators[0] + + // create a new account + info, _, err := val.ClientCtx.Keyring.NewMnemonic("NewValidator", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Secp256k1) + s.Require().NoError(err) + + account := sdk.AccAddress(info.GetPubKey().Address()) + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + account, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(2000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + // Create new bls account in the keyring. + aliceInfo, _, err := val.ClientCtx.Keyring.NewMnemonic("alice", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Bls12381) + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + aliceAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(2000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + // perform a transaction to set pop for bls public key + bobInfo, _, err := val.ClientCtx.Keyring.NewMnemonic("bob", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Bls12381) + s.Require().NoError(err) + bobAddr := sdk.AccAddress(bobInfo.GetPubKey().Address()) + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + aliceAddr, + bobAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(1000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + charlieInfo, _, err := val.ClientCtx.Keyring.NewMnemonic("charlie", keyring.English, sdk.FullFundraiserPath, keyring.DefaultBIP39Passphrase, hd.Bls12381) + s.Require().NoError(err) + charlieAddr := sdk.AccAddress(charlieInfo.GetPubKey().Address()) + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + bobAddr, + charlieAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(800))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + charlieAddr, + bobAddr, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(300))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + // create a group + validMembers := fmt.Sprintf(`{"members":[{"address":"%s","weight":"3","metadata":"%s"}]}`, val.Address.String(), validMetadata) + validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) + out, err := cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateGroupCmd(), + append( + []string{ + val.Address.String(), + validMetadata, + validMembersFile.Name(), + }, + commonFlags..., + ), + ) + + s.Require().NoError(err, out.String()) + var txResp = sdk.TxResponse{} + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + s.group = &group.GroupInfo{GroupId: 1, Admin: val.Address.String(), Metadata: []byte{1}, TotalWeight: "3", Version: 1} + + // create 5 group accounts + for i := 0; i < 5; i++ { + threshold := i + 1 + if threshold > 3 { + threshold = 3 + } + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateGroupAccountCmd(), + append( + []string{ + val.Address.String(), + "1", + validMetadata, + fmt.Sprintf("{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"%d\", \"timeout\":\"30000s\"}", threshold), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryGroupAccountsByGroupCmd(), []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + } + + var res group.QueryGroupAccountsByGroupResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + s.Require().Equal(len(res.GroupAccounts), 5) + s.groupAccounts = res.GroupAccounts + + // create a proposal + validTxFileName := getTxSendFileName(s, s.groupAccounts[0].Address, val.Address.String()) + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateProposalCmd(), + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + // vote + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgVoteCmd(), + append( + []string{ + "1", + val.Address.String(), + "CHOICE_YES", + "", + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryProposalCmd(), []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + + var proposalRes group.QueryProposalResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &proposalRes)) + s.proposal = proposalRes.Proposal + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryVoteByProposalVoterCmd(), []string{"1", val.Address.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + + var voteRes group.QueryVoteByProposalVoterResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &voteRes)) + s.vote = voteRes.Vote + + // Create a bls-only group + validBlsMembers := fmt.Sprintf(`{"members": [ + { + "address": "%s", + "weight": "1", + "metadata": "%s" + }, + { + "address": "%s", + "weight": "2", + "metadata": "%s" + }, + { + "address": "%s", + "weight": "3", + "metadata": "%s" + }]}`, aliceAddr.String(), validMetadata, bobAddr.String(), validMetadata, charlieAddr.String(), validMetadata) + validBlsMembersFile := testutil.WriteToNewTempFile(s.T(), validBlsMembers) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateGroupCmd(), + append( + []string{ + aliceAddr.String(), + validMetadata, + validBlsMembersFile.Name(), + fmt.Sprintf("--%s", client.FlagBlsOnly), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + s.groupBls = &group.GroupInfo{GroupId: 2, Admin: aliceAddr.String(), Metadata: []byte{1}, TotalWeight: "6", Version: 1} + + // create 5 group accounts + for i := 0; i < 5; i++ { + threshold := i + 1 + if threshold > 4 { + threshold = 4 + } + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateGroupAccountCmd(), + append( + []string{ + aliceAddr.String(), + "2", + validMetadata, + fmt.Sprintf("{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"%d\", \"timeout\":\"30000s\"}", threshold), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryGroupAccountsByGroupCmd(), []string{"2", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + } + + var resBls group.QueryGroupAccountsByGroupResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &resBls)) + s.Require().Equal(len(resBls.GroupAccounts), 5) + s.groupAccountsBls = resBls.GroupAccounts + + // give group account 0 some balance + blsAddr0, err := sdk.AccAddressFromBech32(s.groupAccountsBls[0].Address) + s.Require().NoError(err) + _, err = banktestutil.MsgSendExec( + val.ClientCtx, + val.Address, + blsAddr0, + sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(2000))), fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + ) + s.Require().NoError(err) + + // create a proposal for bls group + validTxFileNameBls := getTxSendFileName(s, s.groupAccountsBls[0].Address, aliceAddr.String()) + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateProposalCmd(), + append( + []string{ + s.groupAccountsBls[0].Address, + aliceAddr.String(), + validTxFileNameBls, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, aliceAddr.String()), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryProposalCmd(), []string{"2", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &proposalRes)) + s.proposalBls = proposalRes.Proposal + + // create a poll for bls group + now := time.Now() + expiryTime := now.Add(time.Second * 3000) + expiry, err := gogotypes.TimestampProto(expiryTime) + s.Require().NoError(err) + expiryStr := expiry.String() + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreatePollCmd(), + append( + []string{ + aliceAddr.String(), + "2", + "2022 Election", + "alice,bob,charlie,linda,tom", + "2", + expiryStr, + "", + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + // vote-poll + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgVotePollCmd(), + append( + []string{ + "1", + aliceAddr.String(), + "alice,linda", + "", + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + var pollRes group.QueryPollResponse + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryPollCmd(), []string{"1", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &pollRes)) + s.pollBls = pollRes.Poll + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryVoteForPollByPollVoterCmd(), []string{"1", aliceAddr.String(), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + var votePollRes group.QueryVoteForPollByPollVoterResponse + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &votePollRes)) + s.votePoll = votePollRes.Vote +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.T().Log("tearing down integration test suite") + s.network.Cleanup() +} + +func (s *IntegrationTestSuite) TestTxCreateGroup() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + validMembers := fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "1", + "metadata": "%s" + }]}`, val.Address.String(), validMetadata) + validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) + + invalidMembersAddress := `{"members": [{ + "address": "", + "weight": "1" +}]}` + invalidMembersAddressFile := testutil.WriteToNewTempFile(s.T(), invalidMembersAddress) + + invalidMembersWeight := fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "0" + }]}`, val.Address.String()) + invalidMembersWeightFile := testutil.WriteToNewTempFile(s.T(), invalidMembersWeight) + + invalidMembersMetadata := fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "1", + "metadata": "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }]}`, val.Address.String()) + invalidMembersMetadataFile := testutil.WriteToNewTempFile(s.T(), invalidMembersMetadata) + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + val.Address.String(), + "", + validMembersFile.Name(), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + val.Address.String(), + "", + validMembersFile.Name(), + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "group metadata too long", + append( + []string{ + val.Address.String(), + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + "", + }, + commonFlags..., + ), + true, + "group metadata: limit exceeded", + nil, + 0, + }, + { + "invalid members address", + append( + []string{ + val.Address.String(), + "null", + invalidMembersAddressFile.Name(), + }, + commonFlags..., + ), + true, + "message validation failed: members: address: empty address string is not allowed", + nil, + 0, + }, + { + "invalid members weight", + append( + []string{ + val.Address.String(), + "null", + invalidMembersWeightFile.Name(), + }, + commonFlags..., + ), + true, + "message validation failed: member weight: expected a positive decimal, got 0", + nil, + 0, + }, + { + "members metadata too long", + append( + []string{ + val.Address.String(), + "null", + invalidMembersMetadataFile.Name(), + }, + commonFlags..., + ), + true, + "member metadata: limit exceeded", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgCreateGroupCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxUpdateGroupAdmin() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + validMembers := fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "1", + "metadata": "%s" + }]}`, val.Address.String(), validMetadata) + validMembersFile := testutil.WriteToNewTempFile(s.T(), validMembers) + out, err := cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateGroupCmd(), + append( + []string{ + val.Address.String(), + validMetadata, + validMembersFile.Name(), + }, + commonFlags..., + ), + ) + + s.Require().NoError(err, out.String()) + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + val.Address.String(), + "4", + s.network.Validators[1].Address.String(), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + val.Address.String(), + "5", + s.network.Validators[1].Address.String(), + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "group id invalid", + append( + []string{ + val.Address.String(), + "", + s.network.Validators[1].Address.String(), + }, + commonFlags..., + ), + true, + "strconv.ParseUint: parsing \"\": invalid syntax", + nil, + 0, + }, + { + "group doesn't exist", + append( + []string{ + val.Address.String(), + "12345", + s.network.Validators[1].Address.String(), + }, + commonFlags..., + ), + true, + "not found", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgUpdateGroupAdminCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxUpdateGroupMetadata() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + val.Address.String(), + "3", + validMetadata, + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + val.Address.String(), + "3", + validMetadata, + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "group metadata too long", + append( + []string{ + val.Address.String(), + strconv.FormatUint(s.group.GroupId, 10), + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + }, + commonFlags..., + ), + true, + "metadata: limit exceeded", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgUpdateGroupMetadataCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxUpdateGroupMembers() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + validUpdatedMembersFileName := testutil.WriteToNewTempFile(s.T(), fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "0", + "metadata": "%s" + }, { + "address": "%s", + "weight": "1", + "metadata": "%s" + }]}`, val.Address.String(), validMetadata, s.groupAccounts[0].Address, validMetadata)).Name() + + invalidMembersMetadata := fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "1", + "metadata": "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==" + }]}`, val.Address.String()) + invalidMembersMetadataFileName := testutil.WriteToNewTempFile(s.T(), invalidMembersMetadata).Name() + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + val.Address.String(), + "3", + validUpdatedMembersFileName, + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + val.Address.String(), + "3", + testutil.WriteToNewTempFile(s.T(), fmt.Sprintf(`{"members": [{ + "address": "%s", + "weight": "2", + "metadata": "%s" + }]}`, s.groupAccounts[0].Address, validMetadata)).Name(), + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "group member metadata too long", + append( + []string{ + val.Address.String(), + strconv.FormatUint(s.group.GroupId, 10), + invalidMembersMetadataFileName, + }, + commonFlags..., + ), + true, + "member metadata: limit exceeded", + nil, + 0, + }, + { + "group doesn't exist", + append( + []string{ + val.Address.String(), + "12345", + validUpdatedMembersFileName, + }, + commonFlags..., + ), + true, + "not found", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgUpdateGroupMembersCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxCreateGroupAccount() { + val := s.network.Validators[0] + wrongAdmin := s.network.Validators[1].Address + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + groupID := s.group.GroupId + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + val.Address.String(), + fmt.Sprintf("%v", groupID), + validMetadata, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + val.Address.String(), + fmt.Sprintf("%v", groupID), + validMetadata, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "wrong admin", + append( + []string{ + wrongAdmin.String(), + fmt.Sprintf("%v", groupID), + validMetadata, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + }, + commonFlags..., + ), + true, + "key not found", + &sdk.TxResponse{}, + 0, + }, + { + "metadata too long", + append( + []string{ + val.Address.String(), + fmt.Sprintf("%v", groupID), + strings.Repeat("a", 500), + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + }, + commonFlags..., + ), + true, + "metadata: limit exceeded", + &sdk.TxResponse{}, + 0, + }, + { + "wrong group id", + append( + []string{ + val.Address.String(), + "10", + validMetadata, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + }, + commonFlags..., + ), + true, + "not found", + &sdk.TxResponse{}, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgCreateGroupAccountCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxUpdateGroupAccountAdmin() { + val := s.network.Validators[0] + newAdmin := s.network.Validators[1].Address + clientCtx := val.ClientCtx + groupAccount := s.groupAccounts[3] + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + groupAccount.Admin, + groupAccount.Address, + newAdmin.String(), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + groupAccount.Admin, + s.groupAccounts[4].Address, + newAdmin.String(), + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "wrong admin", + append( + []string{ + newAdmin.String(), + groupAccount.Address, + newAdmin.String(), + }, + commonFlags..., + ), + true, + "key not found", + &sdk.TxResponse{}, + 0, + }, + { + "wrong group account", + append( + []string{ + groupAccount.Admin, + newAdmin.String(), + newAdmin.String(), + }, + commonFlags..., + ), + true, + "load group account: not found", + &sdk.TxResponse{}, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgUpdateGroupAccountAdminCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxUpdateGroupAccountDecisionPolicy() { + val := s.network.Validators[0] + newAdmin := s.network.Validators[1].Address + clientCtx := val.ClientCtx + groupAccount := s.groupAccounts[2] + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + groupAccount.Admin, + groupAccount.Address, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"40000s\"}", + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + groupAccount.Admin, + groupAccount.Address, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"50000s\"}", + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "wrong admin", + append( + []string{ + newAdmin.String(), + groupAccount.Address, + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + }, + commonFlags..., + ), + true, + "key not found", + &sdk.TxResponse{}, + 0, + }, + { + "wrong group account", + append( + []string{ + groupAccount.Admin, + newAdmin.String(), + "{\"@type\":\"/regen.group.v1alpha1.ThresholdDecisionPolicy\", \"threshold\":\"1\", \"timeout\":\"1s\"}", + }, + commonFlags..., + ), + true, + "load group account: not found", + &sdk.TxResponse{}, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgUpdateGroupAccountDecisionPolicyCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxUpdateGroupAccountMetadata() { + val := s.network.Validators[0] + newAdmin := s.network.Validators[1].Address + clientCtx := val.ClientCtx + groupAccount := s.groupAccounts[2] + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + groupAccount.Admin, + groupAccount.Address, + validMetadata, + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + groupAccount.Admin, + groupAccount.Address, + validMetadata, + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "long metadata", + append( + []string{ + groupAccount.Admin, + groupAccount.Address, + strings.Repeat("a", 500), + }, + commonFlags..., + ), + true, + "group account metadata: limit exceeded", + &sdk.TxResponse{}, + 0, + }, + { + "wrong admin", + append( + []string{ + newAdmin.String(), + groupAccount.Address, + validMetadata, + }, + commonFlags..., + ), + true, + "key not found", + &sdk.TxResponse{}, + 0, + }, + { + "wrong group account", + append( + []string{ + groupAccount.Admin, + newAdmin.String(), + validMetadata, + }, + commonFlags..., + ), + true, + "load group account: not found", + &sdk.TxResponse{}, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgUpdateGroupAccountMetadataCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxCreateProposal() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + validTxFileName := getTxSendFileName(s, s.groupAccounts[0].Address, val.Address.String()) + unauthzTxFileName := getTxSendFileName(s, val.Address.String(), s.groupAccounts[0].Address) + validTxFileName2 := getTxSendFileName(s, s.groupAccounts[3].Address, val.Address.String()) + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with try exec", + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=try", client.FlagExec), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with try exec, not enough yes votes for proposal to pass", + append( + []string{ + s.groupAccounts[3].Address, + val.Address.String(), + validTxFileName2, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=try", client.FlagExec), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "metadata too long", + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + validTxFileName, + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "metadata: limit exceeded", + nil, + 0, + }, + { + "unauthorized msg", + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + unauthzTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "msg does not have group account authorization: unauthorized", + nil, + 0, + }, + { + "invalid proposers", + append( + []string{ + s.groupAccounts[0].Address, + "invalid", + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "proposers: decoding bech32 failed", + nil, + 0, + }, + { + "invalid group account", + append( + []string{ + "invalid", + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "group account: decoding bech32 failed", + nil, + 0, + }, + { + "no group account", + append( + []string{ + val.Address.String(), + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "group account: not found", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgCreateProposalCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxVote() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + validTxFileName := getTxSendFileName(s, s.groupAccounts[1].Address, val.Address.String()) + for i := 0; i < 2; i++ { + out, err := cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateProposalCmd(), + append( + []string{ + s.groupAccounts[1].Address, + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + } + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + "3", + val.Address.String(), + "CHOICE_YES", + "", + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with try exec", + append( + []string{ + "8", + val.Address.String(), + "CHOICE_YES", + "", + fmt.Sprintf("--%s=try", client.FlagExec), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with try exec, not enough yes votes for proposal to pass", + append( + []string{ + "9", + val.Address.String(), + "CHOICE_NO", + "", + fmt.Sprintf("--%s=try", client.FlagExec), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + "6", + val.Address.String(), + "CHOICE_YES", + "", + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "invalid proposal id", + append( + []string{ + "abcd", + val.Address.String(), + "CHOICE_YES", + "", + }, + commonFlags..., + ), + true, + "invalid syntax", + nil, + 0, + }, + { + "proposal not found", + append( + []string{ + "1234", + val.Address.String(), + "CHOICE_YES", + "", + }, + commonFlags..., + ), + true, + "proposal: not found", + nil, + 0, + }, + { + "metadata too long", + append( + []string{ + "3", + val.Address.String(), + "CHOICE_YES", + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + }, + commonFlags..., + ), + true, + "metadata: limit exceeded", + nil, + 0, + }, + { + "invalid choice", + append( + []string{ + "3", + val.Address.String(), + "INVALID_CHOICE", + "", + }, + commonFlags..., + ), + true, + "not a valid vote choice", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgVoteCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxVoteAgg() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + aliceInfo, err := clientCtx.Keyring.Key("alice") + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + + bobInfo, err := clientCtx.Keyring.Key("bob") + s.Require().NoError(err) + bobAddr := sdk.AccAddress(bobInfo.GetPubKey().Address()) + + charlieInfo, err := clientCtx.Keyring.Key("charlie") + s.Require().NoError(err) + charlieAddr := sdk.AccAddress(charlieInfo.GetPubKey().Address()) + + // query group members + cmd := client.QueryGroupMembersCmd() + out, err := cli.ExecTestCLICmd(clientCtx, cmd, []string{strconv.FormatUint(s.groupBls.GroupId, 10), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + var res group.QueryGroupMembersResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + fileGroupMembers := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + + // create a proposal for bls group + var txResp = sdk.TxResponse{} + validTxFileNameBls := getTxSendFileName(s, s.groupAccountsBls[3].Address, aliceAddr.String()) + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateProposalCmd(), + append( + []string{ + s.groupAccountsBls[3].Address, + aliceAddr.String(), + validTxFileNameBls, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, aliceAddr.String()), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + voteFlags := []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + } + + now := time.Now() + expiryTime := now.Add(time.Second * 30) + expiry, err := gogotypes.TimestampProto(expiryTime) + s.Require().NoError(err) + expiryStr := expiry.String() + + // basic vote from alice + cmd = client.GetVoteBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + aliceAddr.String(), + "2", + expiryStr, + "CHOICE_YES", + }, + voteFlags..., + ), + ) + aliceVoteYes := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + + cmd = client.GetVerifyVoteBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, []string{aliceVoteYes}) + s.Require().NoError(err) + + // basic vote from bob + cmd = client.GetVoteBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + bobAddr.String(), + "2", + expiryStr, + "CHOICE_NO", + }, + voteFlags..., + ), + ) + bobVoteNo := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + + cmd = client.GetVerifyVoteBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, []string{bobVoteNo}) + s.Require().NoError(err) + + // basic vote from charlie + cmd = client.GetVoteBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + charlieAddr.String(), + "2", + expiryStr, + "CHOICE_YES", + }, + voteFlags..., + ), + ) + charlieVoteYes := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + cmd = client.GetVerifyVoteBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, []string{charlieVoteYes}) + s.Require().NoError(err) + + // aggregate everyone's vote + cmd = client.MsgVoteAggCmd() + voteAggFlags := append(commonFlags, fmt.Sprintf("--%s=try", client.FlagExec)) + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + aliceAddr.String(), + "2", + expiryStr, + fileGroupMembers, + aliceVoteYes, + bobVoteNo, + charlieVoteYes, + }, + voteAggFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + var proposalRes group.QueryProposalResponse + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryProposalCmd(), []string{"2", fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &proposalRes)) + s.Require().Equal(proposalRes.Proposal.Status, group.ProposalStatusClosed) + s.Require().Equal(proposalRes.Proposal.Result, group.ProposalResultAccepted) + s.Require().Equal(proposalRes.Proposal.ExecutorResult, group.ProposalExecutorResultSuccess) +} + +func (s *IntegrationTestSuite) TestTxExec() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + // create proposals and vote + for i := 4; i <= 5; i++ { + validTxFileName := getTxSendFileName(s, s.groupAccounts[0].Address, val.Address.String()) + out, err := cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreateProposalCmd(), + append( + []string{ + s.groupAccounts[0].Address, + val.Address.String(), + validTxFileName, + "", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgVoteCmd(), + append( + []string{ + fmt.Sprintf("%d", i), + val.Address.String(), + "CHOICE_YES", + "", + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + } + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + "4", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "with amino-json", + append( + []string{ + "5", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + fmt.Sprintf("--%s=%s", flags.FlagSignMode, flags.SignModeLegacyAminoJSON), + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "invalid proposal id", + append( + []string{ + "abcd", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "invalid syntax", + nil, + 0, + }, + { + "proposal not found", + append( + []string{ + "1234", + fmt.Sprintf("--%s=%s", flags.FlagFrom, val.Address.String()), + }, + commonFlags..., + ), + true, + "proposal: not found", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgExecCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxCreatePoll() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + aliceInfo, err := clientCtx.Keyring.Key("alice") + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + + now := time.Now() + deadline := now.Add(time.Second * 3000) + timeout, err := gogotypes.TimestampProto(deadline) + s.Require().NoError(err) + timeoutStr := timeout.String() + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + aliceAddr.String(), + "2", + "2023 Election", + "alice,bob,charlie,eva", + "2", + timeoutStr, + validMetadata, + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "poll expired", + append( + []string{ + aliceAddr.String(), + "2", + "2022 Election", + "alice,bob,charlie", + "2", + "2021-08-15T12:00:00Z", + validMetadata, + }, + commonFlags..., + ), + true, + "deadline of the poll has passed", + nil, + 0, + }, + { + "title too long", + append( + []string{ + aliceAddr.String(), + "2", + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + "alice,bob,charlie", + "2", + timeoutStr, + validMetadata, + }, + commonFlags..., + ), + true, + "poll title: limit exceeded", + nil, + 0, + }, + { + "metadata too long", + append( + []string{ + aliceAddr.String(), + "2", + "2022 Election", + "alice,bob,charlie", + "2", + timeoutStr, + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + }, + commonFlags..., + ), + true, + "metadata: limit exceeded", + nil, + 0, + }, + { + "invalid creator", + append( + []string{ + "invalid", + "2", + "2022 Election", + "alice,bob,charlie", + "2", + timeoutStr, + "", + }, + commonFlags..., + ), + true, + "invalid.info: key not found", + nil, + 0, + }, + { + "invalid group id", + append( + []string{ + aliceAddr.String(), + "invalid", + "2022 Election", + "alice,bob,charlie,linda,tom", + "2", + timeoutStr, + validMetadata, + }, + commonFlags..., + ), + true, + "strconv.ParseUint: parsing", + nil, + 0, + }, + { + "invalid limit", + append( + []string{ + aliceAddr.String(), + "2", + "2022 Election", + "alice,bob,charlie", + "5", + timeoutStr, + validMetadata, + }, + commonFlags..., + ), + true, + "vote limit exceeds the number of options: invalid value", + nil, + 0, + }, + { + "repeated options", + append( + []string{ + aliceAddr.String(), + "2", + "2022 Election", + "alice,bob,bob", + "2", + timeoutStr, + validMetadata, + }, + commonFlags..., + ), + true, + "duplicate value", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgCreatePollCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxVotePoll() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + aliceInfo, err := clientCtx.Keyring.Key("alice") + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + + testCases := []struct { + name string + args []string + expectErr bool + expectErrMsg string + respType proto.Message + expectedCode uint32 + }{ + { + "correct data", + append( + []string{ + "2", + aliceAddr.String(), + "alice,bob", + "", + }, + commonFlags..., + ), + false, + "", + &sdk.TxResponse{}, + 0, + }, + { + "invalid poll id", + append( + []string{ + "abcd", + aliceAddr.String(), + "alice,bob", + "", + }, + commonFlags..., + ), + true, + "invalid syntax", + nil, + 0, + }, + { + "poll not found", + append( + []string{ + "1234", + aliceAddr.String(), + "alice,bob", + "", + }, + commonFlags..., + ), + true, + "load poll: not found", + nil, + 0, + }, + { + "metadata too long", + append( + []string{ + "1", + aliceAddr.String(), + "alice,bob", + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ==", + }, + commonFlags..., + ), + true, + "metadata: limit exceeded", + nil, + 0, + }, + } + + for _, tc := range testCases { + tc := tc + + s.Run(tc.name, func() { + cmd := client.MsgVotePollCmd() + + out, err := cli.ExecTestCLICmd(clientCtx, cmd, tc.args) + if tc.expectErr { + s.Require().Contains(out.String(), tc.expectErrMsg) + } else { + s.Require().NoError(err, out.String()) + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType), out.String()) + + txResp := tc.respType.(*sdk.TxResponse) + s.Require().Equal(tc.expectedCode, txResp.Code, out.String()) + } + }) + } +} + +func (s *IntegrationTestSuite) TestTxVotePollAgg() { + val := s.network.Validators[0] + clientCtx := val.ClientCtx + + var commonFlags = []string{ + fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), + fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastBlock), + fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin(s.cfg.BondDenom, sdk.NewInt(10))).String()), + } + + aliceInfo, err := clientCtx.Keyring.Key("alice") + s.Require().NoError(err) + aliceAddr := sdk.AccAddress(aliceInfo.GetPubKey().Address()) + + bobInfo, err := clientCtx.Keyring.Key("bob") + s.Require().NoError(err) + bobAddr := sdk.AccAddress(bobInfo.GetPubKey().Address()) + + charlieInfo, err := clientCtx.Keyring.Key("charlie") + s.Require().NoError(err) + charlieAddr := sdk.AccAddress(charlieInfo.GetPubKey().Address()) + + // query group members + cmd := client.QueryGroupMembersCmd() + out, err := cli.ExecTestCLICmd(clientCtx, cmd, []string{strconv.FormatUint(s.groupBls.GroupId, 10), fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + var res group.QueryGroupMembersResponse + s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &res)) + fileGroupMembers := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + + now := time.Now() + timeout, err := gogotypes.TimestampProto(now.Add(time.Second * 3000)) + s.Require().NoError(err) + + expiry, err := gogotypes.TimestampProto(now.Add(time.Second * 1000)) + s.Require().NoError(err) + expiryStr := expiry.String() + + // create a poll for bls group + var txResp = sdk.TxResponse{} + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.MsgCreatePollCmd(), + append( + []string{ + aliceAddr.String(), + "2", + "2024 Election", + "alice,bob,clare,david,eva,fred,george", + "3", + timeout.String(), + "", + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + voteFlags := []string{ + fmt.Sprintf("--%s=json", tmcli.OutputFlag), + } + + pollID := "3" + + // basic vote from alice + cmd = client.GetVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + aliceAddr.String(), + pollID, + expiryStr, + "alice", + "david", + "eva", + }, + voteFlags..., + ), + ) + s.Require().NoError(err) + aliceVote := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + + cmd = client.GetVerifyVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, []string{aliceVote}) + s.Require().NoError(err) + + // basic vote from bob + cmd = client.GetVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + bobAddr.String(), + pollID, + expiryStr, + "bob", + "david", + }, + voteFlags..., + ), + ) + s.Require().NoError(err) + bobVote := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + + cmd = client.GetVerifyVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, []string{bobVote}) + s.Require().NoError(err) + + // basic vote from charlie + cmd = client.GetVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + charlieAddr.String(), + pollID, + expiryStr, + "david", + "eva", + }, + voteFlags..., + ), + ) + s.Require().NoError(err) + charlieVote := testutil.WriteToNewTempFile(s.T(), out.String()).Name() + cmd = client.GetVerifyVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, []string{charlieVote}) + s.Require().NoError(err) + + // aggregate everyone's vote + cmd = client.MsgVotePollAggCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + aliceAddr.String(), + pollID, + expiryStr, + fileGroupMembers, + aliceVote, + bobVote, + charlieVote, + }, + commonFlags..., + ), + ) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &txResp), out.String()) + s.Require().Equal(uint32(0), txResp.Code, out.String()) + + var pollRes group.QueryPollResponse + out, err = cli.ExecTestCLICmd(val.ClientCtx, client.QueryPollCmd(), []string{pollID, fmt.Sprintf("--%s=json", tmcli.OutputFlag)}) + s.Require().NoError(err, out.String()) + s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &pollRes)) + s.Require().Equal(pollRes.Poll.Status, group.PollStatusSubmitted) + s.Require().Equal(pollRes.Poll.VoteState.Counts, map[string]string{ + "alice": "1", "bob": "2", "david": "6", "eva": "4", + }) + + // test invalid + // duplicate options in basic votes + cmd = client.GetVotePollBasicCmd() + out, err = cli.ExecTestCLICmd(clientCtx, cmd, + append( + []string{ + aliceAddr.String(), + pollID, + expiryStr, + "alice", + "alice", + }, + voteFlags..., + ), + ) + s.Require().Contains(err.Error(), "duplicate value") +} + +func getTxSendFileName(s *IntegrationTestSuite, from string, to string) string { + tx := fmt.Sprintf( + `{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"%s","to_address":"%s","amount":[{"denom":"%s","amount":"10"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""}},"signatures":[]}`, + from, to, s.cfg.BondDenom, + ) + return testutil.WriteToNewTempFile(s.T(), tx).Name() +} diff --git a/x/group/client/tx.go b/x/group/client/tx.go new file mode 100644 index 0000000000..b18254bd7e --- /dev/null +++ b/x/group/client/tx.go @@ -0,0 +1,1338 @@ +package client + +import ( + "encoding/base64" + "fmt" + "sort" + + "strconv" + "strings" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + + "github.com/gogo/protobuf/types" + tmcli "github.com/tendermint/tendermint/libs/cli" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/version" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/x/group" + gogotypes "github.com/gogo/protobuf/types" +) + +const ( + FlagExec = "exec" + ExecTry = "try" + FlagBlsOnly = "bls" +) + +// TxCmd returns a root CLI command handler for all x/group transaction commands. +func TxCmd(name string) *cobra.Command { + txCmd := &cobra.Command{ + Use: name, + Short: "Group transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + MsgCreateGroupCmd(), + MsgUpdateGroupAdminCmd(), + MsgUpdateGroupMetadataCmd(), + MsgUpdateGroupMembersCmd(), + MsgCreateGroupAccountCmd(), + MsgUpdateGroupAccountAdminCmd(), + MsgUpdateGroupAccountDecisionPolicyCmd(), + MsgUpdateGroupAccountMetadataCmd(), + MsgCreateProposalCmd(), + MsgCreatePollCmd(), + MsgVoteCmd(), + MsgVoteAggCmd(), + MsgExecCmd(), + MsgVotePollCmd(), + MsgVotePollAggCmd(), + GetVoteBasicCmd(), + GetVerifyVoteBasicCmd(), + GetVotePollBasicCmd(), + GetVerifyVotePollBasicCmd(), + ) + + return txCmd +} + +// MsgCreateGroupCmd creates a CLI command for Msg/CreateGroup. +func MsgCreateGroupCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-group [admin] [metadata] [members-json-file]", + Short: "Create a group which is an aggregation " + + "of member accounts with associated weights and " + + "an administrator account. Note, the '--from' flag is " + + "ignored as it is implied from [admin].", + Long: strings.TrimSpace( + fmt.Sprintf(`Create a group which is an aggregation of member accounts with associated weights and +an administrator account. Note, the '--from' flag is ignored as it is implied from [admin]. +Members accounts can be given through a members JSON file that contains an array of members. + +Example: +$ %s tx group create-group [admin] [metadata] [members-json-file] + +Where members.json contains: + +{ + "members": [ + { + "address": "addr1", + "weight": "1", + "metadata": "some metadata" + }, + { + "address": "addr2", + "weight": "1", + "metadata": "some metadata" + } + ] +} +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + members, err := parseMembers(clientCtx, args[2]) + if err != nil { + return err + } + + b, err := base64.StdEncoding.DecodeString(args[1]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + bls, _ := cmd.Flags().GetBool(FlagBlsOnly) + + msg := &group.MsgCreateGroup{ + Admin: clientCtx.GetFromAddress().String(), + Members: members, + Metadata: b, + BlsOnly: bls, + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + cmd.Flags().Bool(FlagBlsOnly, false, "Only accept members with bls public keys") + + return cmd +} + +// MsgUpdateGroupMembersCmd creates a CLI command for Msg/UpdateGroupMembers. +func MsgUpdateGroupMembersCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-group-members [admin] [group-id] [members-json-file]", + Short: "Update a group's members. Set a member's weight to \"0\" to delete it.", + Long: strings.TrimSpace( + fmt.Sprintf(`Update a group's members + +Example: +$ %s tx group update-group-members [admin] [group-id] [members-json-file] + +Where members.json contains: + +{ + "members": [ + { + "address": "addr1", + "weight": "1", + "metadata": "some new metadata" + }, + { + "address": "addr2", + "weight": "0", + "metadata": "some metadata" + } + ] +} + +Set a member's weight to "0" to delete it. +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + members, err := parseMembers(clientCtx, args[2]) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + msg := &group.MsgUpdateGroupMembers{ + Admin: clientCtx.GetFromAddress().String(), + MemberUpdates: members, + GroupId: groupID, + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgUpdateGroupAdminCmd creates a CLI command for Msg/UpdateGroupAdmin. +func MsgUpdateGroupAdminCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-group-admin [admin] [group-id] [new-admin]", + Short: "Update a group's admin", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + msg := &group.MsgUpdateGroupAdmin{ + Admin: clientCtx.GetFromAddress().String(), + NewAdmin: args[2], + GroupId: groupID, + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgUpdateGroupMetadataCmd creates a CLI command for Msg/UpdateGroupMetadata. +func MsgUpdateGroupMetadataCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-group-metadata [admin] [group-id] [metadata]", + Short: "Update a group's metadata", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + b, err := base64.StdEncoding.DecodeString(args[2]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + msg := &group.MsgUpdateGroupMetadata{ + Admin: clientCtx.GetFromAddress().String(), + Metadata: b, + GroupId: groupID, + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgCreateGroupAccountCmd creates a CLI command for Msg/CreateGroupAccount. +func MsgCreateGroupAccountCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-group-account [admin] [group-id] [metadata] [decision-policy]", + Short: "Create a group account which is an account " + + "associated with a group and a decision policy. " + + "Note, the '--from' flag is " + + "ignored as it is implied from [admin].", + Long: strings.TrimSpace( + fmt.Sprintf(`Create a group account which is an account associated with a group and a decision policy. +Note, the '--from' flag is ignored as it is implied from [admin]. + +Example: +$ %s tx group create-group-account [admin] [group-id] [metadata] \ +'{"@type":"/regen.group.v1alpha1.ThresholdDecisionPolicy", "threshold":"1", "timeout":"1s"}' +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + var policy group.DecisionPolicy + if err := clientCtx.Codec.UnmarshalInterfaceJSON([]byte(args[3]), &policy); err != nil { + return err + } + + b, err := base64.StdEncoding.DecodeString(args[2]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + msg, err := group.NewMsgCreateGroupAccount( + clientCtx.GetFromAddress(), + groupID, + b, + policy, + ) + if err != nil { + return err + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgUpdateGroupAccountAdminCmd creates a CLI command for Msg/UpdateGroupAccountAdmin. +func MsgUpdateGroupAccountAdminCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-group-account-admin [admin] [group-account] [new-admin]", + Short: "Update a group account admin", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := &group.MsgUpdateGroupAccountAdmin{ + Admin: clientCtx.GetFromAddress().String(), + Address: args[1], + NewAdmin: args[2], + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgUpdateGroupAccountDecisionPolicyCmd creates a CLI command for Msg/UpdateGroupAccountDecisionPolicy. +func MsgUpdateGroupAccountDecisionPolicyCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-group-account-policy [admin] [group-account] [decision-policy]", + Short: "Update a group account decision policy", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + var policy group.DecisionPolicy + if err := clientCtx.Codec.UnmarshalInterfaceJSON([]byte(args[2]), &policy); err != nil { + return err + } + + accountAddress, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + msg, err := group.NewMsgUpdateGroupAccountDecisionPolicyRequest( + clientCtx.GetFromAddress(), + accountAddress, + policy, + ) + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgUpdateGroupAccountMetadataCmd creates a CLI command for Msg/MsgUpdateGroupAccountMetadata. +func MsgUpdateGroupAccountMetadataCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-group-account-metadata [admin] [group-account] [new-metadata]", + Short: "Update a group account metadata", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + b, err := base64.StdEncoding.DecodeString(args[2]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + msg := &group.MsgUpdateGroupAccountMetadata{ + Admin: clientCtx.GetFromAddress().String(), + Address: args[1], + Metadata: b, + } + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgCreateProposalCmd creates a CLI command for Msg/CreateProposal. +func MsgCreateProposalCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-proposal [group-account] [proposer[,proposer]*] [msg_tx_json_file] [metadata]", + Short: "Submit a new proposal", + Long: `Submit a new proposal. + +Parameters: + group-account: address of the group account + proposer: comma separated (no spaces) list of proposer account addresses. Example: "addr1,addr2" + Metadata: metadata for the proposal + msg_tx_json_file: path to json file with messages that will be executed if the proposal is accepted. +`, + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + proposers := strings.Split(args[1], ",") + for i := range proposers { + proposers[i] = strings.TrimSpace(proposers[i]) + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + theTx, err := authclient.ReadTxFromFile(clientCtx, args[2]) + if err != nil { + return err + } + msgs := theTx.GetMsgs() + + b, err := base64.StdEncoding.DecodeString(args[3]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + execStr, _ := cmd.Flags().GetString(FlagExec) + + msg, err := group.NewMsgCreateProposalRequest( + args[0], + proposers, + msgs, + b, + execFromString(execStr), + ) + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagExec, "", "Set to 1 to try to execute proposal immediately after creation (proposers signatures are considered as Yes votes)") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgCreatePollCmd creates a CLI command for Msg/CreatePoll. +func MsgCreatePollCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-poll [creator] [group-id] [title] [option[,option]*] [vote-limit] [timeout] [metadata]", + Short: "Submit a new poll", + Long: `Submit a new poll. + +Parameters: + group-id: unique id of the group + title: title of the poll + option: comma separated (no spaces) list of options. Example: "option1,option2" + vote-limit: number of options each voter can choose + time-out: deadline for voting the poll + Metadata: metadata for the poll +`, + Args: cobra.ExactArgs(7), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + groupID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + title := args[2] + + optionTitles := strings.Split(args[3], ",") + for i := range optionTitles { + optionTitles[i] = strings.TrimSpace(optionTitles[i]) + } + options := group.Options{Titles: optionTitles} + + voteLimit, err := strconv.ParseInt(args[4], 10, 32) + if err != nil { + return err + } + + timeString := fmt.Sprintf("\"%s\"", args[5]) + var timeout types.Timestamp + err = clientCtx.Codec.UnmarshalJSON([]byte(timeString), &timeout) + if err != nil { + return err + } + timeNow := gogotypes.TimestampNow() + if timeout.Compare(timeNow) <= 0 { + return fmt.Errorf("deadline of the poll has passed") + } + + b, err := base64.StdEncoding.DecodeString(args[6]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + msg := &group.MsgCreatePoll{ + GroupId: groupID, + Title: title, + Options: options, + Creator: args[0], + VoteLimit: int32(voteLimit), + Metadata: b, + Timeout: timeout, + } + if err = msg.ValidateBasic(); err != nil { + return err + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagExec, "", "Set to 1 to try to execute proposal immediately after creation (proposers signatures are considered as Yes votes)") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgVoteCmd creates a CLI command for Msg/Vote. +func MsgVoteCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote [proposal-id] [voter] [choice] [metadata]", + Short: "Vote on a proposal", + Long: `Vote on a proposal. + +Parameters: + proposal-id: unique ID of the proposal + voter: voter account addresses. + choice: choice of the voter(s) + CHOICE_UNSPECIFIED: no-op + CHOICE_NO: no + CHOICE_YES: yes + CHOICE_ABSTAIN: abstain + CHOICE_VETO: veto + Metadata: metadata for the vote +`, + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[1]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + choice, err := group.ChoiceFromString(args[2]) + if err != nil { + return err + } + + b, err := base64.StdEncoding.DecodeString(args[3]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + execStr, _ := cmd.Flags().GetString(FlagExec) + + msg := &group.MsgVote{ + ProposalId: proposalID, + Voter: args[1], + Choice: choice, + Metadata: b, + Exec: execFromString(execStr), + } + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagExec, "", "Set to 1 to try to execute proposal immediately after voting") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgExecCmd creates a CLI command for Msg/MsgExec. +func MsgExecCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "exec [proposal-id]", + Short: "Execute a proposal", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + msg := &group.MsgExec{ + ProposalId: proposalID, + Signer: clientCtx.GetFromAddress().String(), + } + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func MsgVoteAggCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-agg [sender] [proposal_id] [timeout] [group-members-json-file] [[vote-json-file]...]", + Short: "Aggregate signatures of basic votes into aggregated signature and submit the combined votes", + Long: `Aggregate signatures of basic votes into aggregated signature and submit the combined votes. + +Parameters: + sender: sender's account address + proposal-id: unique ID of the proposal + timeout: UTC time for the submission deadline of the aggregated vote, e.g., 2021-08-15T12:00:00Z + group-members-json-file: path to json file that contains group members + vote-json-file: path to json file that contains a basic vote with a verified signature +`, + Args: cobra.MinimumNArgs(5), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + timeString := fmt.Sprintf("\"%s\"", args[2]) + var timeout types.Timestamp + err = clientCtx.Codec.UnmarshalJSON([]byte(timeString), &timeout) + if err != nil { + return err + } + timeNow := gogotypes.TimestampNow() + if timeout.Compare(timeNow) <= 0 { + return fmt.Errorf("deadline for submitting the vote has passed") + } + + groupMembers, err := parseGroupMembers(clientCtx, args[3]) + if err != nil { + return err + } + for _, mem := range groupMembers { + if err = mem.ValidateBasic(); err != nil { + return err + } + } + + // make sure group members are sorted by their addresses + sorted := sort.SliceIsSorted(groupMembers, func(i, j int) bool { + return groupMembers[i].Member.Address < groupMembers[j].Member.Address + }) + if !sorted { + sort.Slice(groupMembers, func(i, j int) bool { + return groupMembers[i].Member.Address < groupMembers[j].Member.Address + }) + } + + index := make(map[string]int, len(groupMembers)) + for i, mem := range groupMembers { + addr := mem.Member.Address + if _, exists := index[addr]; exists { + return fmt.Errorf("duplicate address: %s", addr) + } + index[addr] = i + } + + votes := make([]group.Choice, len(groupMembers)) + for i := range votes { + votes[i] = group.Choice_CHOICE_UNSPECIFIED + } + + var sigs [][]byte + for i := 4; i < len(args); i++ { + vote, err := parseVoteBasic(clientCtx, args[i]) + if err != nil { + return err + } + + if vote.ProposalId != proposalID || !vote.Expiry.Equal(timeout) { + return fmt.Errorf("invalid vote from %s: expected proposal id %d and timeout %s", vote.Voter, proposalID, timeout.String()) + } + + memIndex, ok := index[vote.Voter] + if !ok { + return fmt.Errorf("invalid voter") + } + + votes[memIndex] = vote.Choice + sigs = append(sigs, vote.Sig) + } + + sigma, err := bls12381.AggregateSignature(sigs) + if err != nil { + return err + } + + execStr, _ := cmd.Flags().GetString(FlagExec) + + msg := &group.MsgVoteAgg{ + Sender: args[0], + ProposalId: proposalID, + Votes: votes, + Expiry: timeout, + AggSig: sigma, + Metadata: nil, + Exec: execFromString(execStr), + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + cmd.Flags().String(FlagExec, "", "Set to 1 to try to execute proposal immediately after voting") + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// MsgVotePollCmd creates a CLI command for Msg/Vote. +func MsgVotePollCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-poll [poll-id] [voter] [option[,option]*] [metadata]", + Short: "Vote on a poll", + Long: `Vote on a poll. + +Parameters: + poll-id: unique ID of the poll + voter: voter account addresses. + option: options chosen by the voter + Metadata: metadata for the vote +`, + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[1]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + pollID, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + optionTitles := strings.Split(args[2], ",") + for i := range optionTitles { + optionTitles[i] = strings.TrimSpace(optionTitles[i]) + } + options := group.Options{Titles: optionTitles} + + b, err := base64.StdEncoding.DecodeString(args[3]) + if err != nil { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "metadata is malformed, proper base64 string is required") + } + + msg := &group.MsgVotePoll{ + PollId: pollID, + Voter: args[1], + Options: options, + Metadata: b, + } + if err != nil { + return err + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func MsgVotePollAggCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-poll-agg [sender] [poll_id] [expiry] [group-members-json-file] [[vote-json-file]...]", + Short: "Aggregate signatures of basic votes into aggregated signature and submit the combined votes", + Long: `Aggregate signatures of basic votes into aggregated signature and submit the combined votes. + +Parameters: + sender: sender's account address + poll-id: unique ID of the poll + timeout: UTC time for the submission deadline of the aggregated vote, e.g., 2021-08-15T12:00:00Z + group-members-json-file: path to json file that contains group members + vote-json-file: path to json file that contains a basic vote with a verified signature +`, + Args: cobra.MinimumNArgs(5), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + pollID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + timeString := fmt.Sprintf("\"%s\"", args[2]) + var timeout types.Timestamp + err = clientCtx.Codec.UnmarshalJSON([]byte(timeString), &timeout) + if err != nil { + return err + } + timeNow := gogotypes.TimestampNow() + if timeout.Compare(timeNow) <= 0 { + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "deadline for submitting the vote has passed") + } + + groupMembers, err := parseGroupMembers(clientCtx, args[3]) + if err != nil { + return err + } + for _, mem := range groupMembers { + if err = mem.ValidateBasic(); err != nil { + return err + } + } + + // make sure group members are sorted by their addresses + sorted := sort.SliceIsSorted(groupMembers, func(i, j int) bool { + return groupMembers[i].Member.Address < groupMembers[j].Member.Address + }) + if !sorted { + sort.Slice(groupMembers, func(i, j int) bool { + return groupMembers[i].Member.Address < groupMembers[j].Member.Address + }) + } + + index := make(map[string]int, len(groupMembers)) + for i, mem := range groupMembers { + addr := mem.Member.Address + if _, exists := index[addr]; exists { + return fmt.Errorf("duplicate address: %s", addr) + } + index[addr] = i + } + + votes := make([]group.Options, len(groupMembers)) + + var sigs [][]byte + for i := 4; i < len(args); i++ { + vote, err := parseVotePollBasic(clientCtx, args[i]) + if err != nil { + return err + } + + if vote.PollId != pollID || !vote.Expiry.Equal(timeout) { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, + "invalid vote from %s: expect poll id %d and timeout %s", vote.Voter, pollID, timeout.String()) + } + + memIndex, ok := index[vote.Voter] + if !ok { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "voter %s", vote.Voter) + } + + votes[memIndex] = vote.Options + sigs = append(sigs, vote.Sig) + } + + sigma, err := bls12381.AggregateSignature(sigs) + if err != nil { + return err + } + + msg := &group.MsgVotePollAgg{ + Sender: args[0], + PollId: pollID, + Votes: votes, + Expiry: timeout, + AggSig: sigma, + Metadata: []byte(fmt.Sprintf("submitted as aggregated vote by account %s", args[0])), + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +// GetVoteBasicCmd creates a CLI command for Msg/VoteBasic. +func GetVoteBasicCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-basic [voter] [proposal-id] [expiry] [choice]", + Short: "Vote on a proposal", + Long: `Vote on a proposal and the vote will be aggregated with other votes. + +Parameters: + voter: voter account addresses. + proposal-id: unique ID of the proposal + choice: choice of the voter(s) + CHOICE_UNSPECIFIED: no-op + CHOICE_NO: no + CHOICE_YES: yes + CHOICE_ABSTAIN: abstain + CHOICE_VETO: veto + timeout: UTC time for the submission deadline of the vote, e.g., 2021-08-15T12:00:00Z +`, + Args: cobra.ExactArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + proposalID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + timeString := fmt.Sprintf("\"%s\"", args[2]) + var expiry types.Timestamp + err = clientCtx.Codec.UnmarshalJSON([]byte(timeString), &expiry) + if err != nil { + return err + } + + timeNow := gogotypes.TimestampNow() + if expiry.Compare(timeNow) <= 0 { + return fmt.Errorf("deadline for submitting the vote has passed") + } + + choice, err := group.ChoiceFromString(args[3]) + if err != nil { + return err + } + + msg := &group.MsgVoteBasic{ + ProposalId: proposalID, + Choice: choice, + Expiry: expiry, + } + + if err = msg.ValidateBasic(); err != nil { + return fmt.Errorf("message validation failed: %w", err) + } + + bytesToSign := msg.GetSignBytes() + sigBytes, pubKey, err := clientCtx.Keyring.Sign(clientCtx.GetFromName(), bytesToSign) + + pubKeyAny, err := codectypes.NewAnyWithValue(pubKey) + if err != nil { + return err + } + + vote := &group.MsgVoteBasicResponse{ + ProposalId: proposalID, + Choice: choice, + Expiry: expiry, + Voter: args[0], + PubKey: pubKeyAny, + Sig: sigBytes, + } + + return clientCtx.PrintProto(vote) + }, + } + + cmd.Flags().String(flags.FlagFrom, "", "Name or address of private key with which to sign") + cmd.Flags().StringP(tmcli.OutputFlag, "o", "text", "Output format (text|json)") + + return cmd +} + +// GetVerifyVoteBasicCmd creates a CLI command for aggregating basic votes. +func GetVerifyVoteBasicCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "verify-vote-basic [file]", + Short: "Verify signature for a basic vote", + Long: `Verify signature for a basic vote. + +Parameters: + file: a basic vote with signature +`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + vote, err := parseVoteBasic(clientCtx, args[0]) + if err != nil { + return err + } + + if err = vote.ValidateBasic(); err != nil { + return err + } + + if err = vote.VerifySignature(); err != nil { + return err + } + + cmd.Println("Verification Successful!") + + return nil + }, + } + + return cmd +} + +// GetVotePollBasicCmd creates a CLI command for Msg/VotePollBasic. +func GetVotePollBasicCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "vote-poll-basic [voter] [poll-id] [expiry] [[option]...] ", + Short: "Vote on a poll", + Long: `Vote on a proposal and the vote will be aggregated with other votes. + +Parameters: + voter: voter account addresses. + proposal-id: unique ID of the proposal + timeout: UTC time for the submission deadline of the vote, e.g., 2021-08-15T12:00:00Z + options: options chosen by the voter(s) +`, + Args: cobra.MinimumNArgs(4), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + pollID, err := strconv.ParseUint(args[1], 10, 64) + if err != nil { + return err + } + + timeString := fmt.Sprintf("\"%s\"", args[2]) + var timeout types.Timestamp + err = clientCtx.Codec.UnmarshalJSON([]byte(timeString), &timeout) + if err != nil { + return err + } + + timeNow := gogotypes.TimestampNow() + if timeout.Compare(timeNow) <= 0 { + return fmt.Errorf("deadline for submitting the vote has passed") + } + + keyInfo, err := clientCtx.Keyring.Key(clientCtx.GetFromName()) + if err != nil { + return err + } + pubKey := keyInfo.GetPubKey() + pubKeyAny, err := codectypes.NewAnyWithValue(pubKey) + if err != nil { + return err + } + + var optionTitles []string + var sigs [][]byte + for i := 3; i < len(args); i++ { + option := args[i] + optionTitles = append(optionTitles, option) + + msg := group.MsgVotePollBasic{ + PollId: pollID, + Option: option, + Expiry: timeout, + } + if err = msg.ValidateBasic(); err != nil { + return err + } + + bytesToSign := msg.GetSignBytes() + sigBytes, _, err := clientCtx.Keyring.Sign(clientCtx.GetFromName(), bytesToSign) + if err != nil { + return err + } + + sigs = append(sigs, sigBytes) + } + + sigBytes, err := bls12381.AggregateSignature(sigs) + if err != nil { + return err + } + + options := group.Options{Titles: optionTitles} + if err = options.ValidateBasic(); err != nil { + return err + } + + vote := &group.MsgVotePollBasicResponse{ + PollId: pollID, + Options: options, + Expiry: timeout, + Voter: args[0], + PubKey: pubKeyAny, + Sig: sigBytes, + } + + return clientCtx.PrintProto(vote) + }, + } + + cmd.Flags().String(flags.FlagFrom, "", "Name or address of private key with which to sign") + cmd.Flags().StringP(tmcli.OutputFlag, "o", "text", "Output format (text|json)") + + return cmd +} + +// GetVerifyVoteBasicCmd creates a CLI command for aggregating basic votes. +func GetVerifyVotePollBasicCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "verify-vote-poll-basic [file]", + Short: "Verify signature for a basic vote for poll", + Long: `Verify signature for a basic vote for poll. + +Parameters: + file: a basic vote for poll with signature +`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + vote, err := parseVotePollBasic(clientCtx, args[0]) + if err != nil { + return err + } + + if err = vote.ValidateBasic(); err != nil { + return err + } + + if err = vote.VerifySignature(); err != nil { + return err + } + + cmd.Println("Verification Successful!") + + return nil + }, + } + + return cmd +} diff --git a/x/group/client/util.go b/x/group/client/util.go new file mode 100644 index 0000000000..0d91589a0a --- /dev/null +++ b/x/group/client/util.go @@ -0,0 +1,103 @@ +package client + +import ( + "fmt" + "io/ioutil" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/x/group" +) + +func parseMembers(clientCtx client.Context, membersFile string) ([]group.Member, error) { + members := group.Members{} + + if membersFile == "" { + return members.Members, nil + } + + contents, err := ioutil.ReadFile(membersFile) + if err != nil { + return nil, err + } + + err = clientCtx.Codec.UnmarshalJSON(contents, &members) + if err != nil { + return nil, err + } + + return members.Members, nil +} + +func execFromString(execStr string) group.Exec { + var exec group.Exec + switch execStr { + case ExecTry: + exec = group.Exec_EXEC_TRY + default: + exec = group.Exec_EXEC_UNSPECIFIED + } + return exec +} + +func parseGroupMembers(clientCtx client.Context, membersFile string) ([]*group.GroupMember, error) { + res := group.QueryGroupMembersResponse{} + + if membersFile == "" { + return res.Members, nil + } + + contents, err := ioutil.ReadFile(membersFile) + if err != nil { + return nil, err + } + err = clientCtx.Codec.UnmarshalJSON(contents, &res) + if err != nil { + return nil, err + } + + if res.Pagination.NextKey != nil { + return nil, fmt.Errorf("require all the group members") + } + + return res.Members, nil +} + +func parseVoteBasic(clientCtx client.Context, voteFile string) (group.MsgVoteBasicResponse, error) { + vote := group.MsgVoteBasicResponse{} + + if voteFile == "" { + return vote, nil + } + + contents, err := ioutil.ReadFile(voteFile) + if err != nil { + return vote, err + } + + err = clientCtx.Codec.UnmarshalJSON(contents, &vote) + if err != nil { + return vote, err + } + + return vote, nil +} + +func parseVotePollBasic(clientCtx client.Context, voteFile string) (group.MsgVotePollBasicResponse, error) { + vote := group.MsgVotePollBasicResponse{} + + if voteFile == "" { + return vote, nil + } + + contents, err := ioutil.ReadFile(voteFile) + if err != nil { + return vote, err + } + + err = clientCtx.Codec.UnmarshalJSON(contents, &vote) + if err != nil { + return vote, err + } + + return vote, nil +} diff --git a/x/group/codec.go b/x/group/codec.go new file mode 100644 index 0000000000..ba80481792 --- /dev/null +++ b/x/group/codec.go @@ -0,0 +1,72 @@ +package group + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +// RegisterLegacyAminoCodec registers all the necessary group module concrete +// types and interfaces with the provided codec reference. +// These types are used for Amino JSON serialization. +func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + cdc.RegisterInterface((*DecisionPolicy)(nil), nil) + cdc.RegisterConcrete(&ThresholdDecisionPolicy{}, "cosmos-sdk/ThresholdDecisionPolicy", nil) + cdc.RegisterConcrete(&MsgCreateGroup{}, "cosmos-sdk/MsgCreateGroup", nil) + cdc.RegisterConcrete(&MsgUpdateGroupMembers{}, "cosmos-sdk/MsgUpdateGroupMembers", nil) + cdc.RegisterConcrete(&MsgUpdateGroupAdmin{}, "cosmos-sdk/MsgUpdateGroupAdmin", nil) + cdc.RegisterConcrete(&MsgUpdateGroupMetadata{}, "cosmos-sdk/MsgUpdateGroupMetadata", nil) + cdc.RegisterConcrete(&MsgCreateGroupAccount{}, "cosmos-sdk/MsgCreateGroupAccount", nil) + cdc.RegisterConcrete(&MsgUpdateGroupAccountAdmin{}, "cosmos-sdk/MsgUpdateGroupAccountAdmin", nil) + cdc.RegisterConcrete(&MsgUpdateGroupAccountDecisionPolicy{}, "cosmos-sdk/MsgUpdateGroupAccountDecisionPolicy", nil) + cdc.RegisterConcrete(&MsgUpdateGroupAccountMetadata{}, "cosmos-sdk/MsgUpdateGroupAccountMetadata", nil) + cdc.RegisterConcrete(&MsgCreateProposal{}, "cosmos-sdk/group/MsgCreateProposal", nil) + cdc.RegisterConcrete(&MsgVote{}, "cosmos-sdk/group/MsgVote", nil) + cdc.RegisterConcrete(&MsgVoteBasicResponse{}, "cosmos-sdk/group/MsgVoteBasic", nil) + cdc.RegisterConcrete(&MsgVoteAgg{}, "cosmos-sdk/group/MsgVoteAgg", nil) + cdc.RegisterConcrete(&MsgExec{}, "cosmos-sdk/group/MsgExec", nil) + cdc.RegisterConcrete(&MsgCreatePoll{}, "cosmos-sdk/group/MsgCreatePoll", nil) + cdc.RegisterConcrete(&MsgVotePoll{}, "cosmos-sdk/group/MsgVotePoll", nil) + cdc.RegisterConcrete(&MsgVotePollBasicResponse{}, "cosmos-sdk/group/MsgVotePollBasic", nil) + cdc.RegisterConcrete(&MsgVotePollAgg{}, "cosmos-sdk/group/MsgVotePollAgg", nil) +} + +func RegisterTypes(registry cdctypes.InterfaceRegistry) { + registry.RegisterImplementations((*sdk.Msg)(nil), + &MsgCreateGroup{}, + &MsgUpdateGroupMembers{}, + &MsgUpdateGroupAdmin{}, + &MsgUpdateGroupMetadata{}, + &MsgCreateGroupAccount{}, + &MsgUpdateGroupAccountAdmin{}, + &MsgUpdateGroupAccountDecisionPolicy{}, + &MsgUpdateGroupAccountMetadata{}, + &MsgCreateProposal{}, + &MsgVote{}, + &MsgVoteBasicResponse{}, + &MsgVoteAgg{}, + &MsgExec{}, + &MsgCreatePoll{}, + &MsgVotePoll{}, + &MsgVotePollBasicResponse{}, + &MsgVotePollAgg{}, + ) + + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) + + registry.RegisterInterface( + "regen.group.v1alpha1.DecisionPolicy", + (*DecisionPolicy)(nil), + &ThresholdDecisionPolicy{}, + ) +} + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewAminoCodec(amino) +) + +func init() { + RegisterLegacyAminoCodec(amino) +} diff --git a/x/group/errors.go b/x/group/errors.go new file mode 100644 index 0000000000..5155ff867b --- /dev/null +++ b/x/group/errors.go @@ -0,0 +1,16 @@ +package group + +import ( + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +var ( + ErrEmpty = sdkerrors.Register(ModuleName, 202, "value is empty") + ErrDuplicate = sdkerrors.Register(ModuleName, 203, "duplicate value") + ErrMaxLimit = sdkerrors.Register(ModuleName, 204, "limit exceeded") + ErrType = sdkerrors.Register(ModuleName, 205, "invalid type") + ErrInvalid = sdkerrors.Register(ModuleName, 206, "invalid value") + ErrUnauthorized = sdkerrors.Register(ModuleName, 207, "unauthorized") + ErrModified = sdkerrors.Register(ModuleName, 208, "modified") + ErrExpired = sdkerrors.Register(ModuleName, 209, "expired") +) diff --git a/x/group/events.pb.go b/x/group/events.pb.go new file mode 100644 index 0000000000..a8f8cf7695 --- /dev/null +++ b/x/group/events.pb.go @@ -0,0 +1,1588 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: regen/group/v1alpha1/events.proto + +package group + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// EventCreateGroup is an event emitted when a group is created. +type EventCreateGroup struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` +} + +func (m *EventCreateGroup) Reset() { *m = EventCreateGroup{} } +func (m *EventCreateGroup) String() string { return proto.CompactTextString(m) } +func (*EventCreateGroup) ProtoMessage() {} +func (*EventCreateGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{0} +} +func (m *EventCreateGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventCreateGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventCreateGroup.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 *EventCreateGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventCreateGroup.Merge(m, src) +} +func (m *EventCreateGroup) XXX_Size() int { + return m.Size() +} +func (m *EventCreateGroup) XXX_DiscardUnknown() { + xxx_messageInfo_EventCreateGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_EventCreateGroup proto.InternalMessageInfo + +func (m *EventCreateGroup) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +// EventUpdateGroup is an event emitted when a group is updated. +type EventUpdateGroup struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` +} + +func (m *EventUpdateGroup) Reset() { *m = EventUpdateGroup{} } +func (m *EventUpdateGroup) String() string { return proto.CompactTextString(m) } +func (*EventUpdateGroup) ProtoMessage() {} +func (*EventUpdateGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{1} +} +func (m *EventUpdateGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventUpdateGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventUpdateGroup.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 *EventUpdateGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventUpdateGroup.Merge(m, src) +} +func (m *EventUpdateGroup) XXX_Size() int { + return m.Size() +} +func (m *EventUpdateGroup) XXX_DiscardUnknown() { + xxx_messageInfo_EventUpdateGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_EventUpdateGroup proto.InternalMessageInfo + +func (m *EventUpdateGroup) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +// EventCreateGroupAccount is an event emitted when a group account is created. +type EventCreateGroupAccount struct { + // address is the address of the group account. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *EventCreateGroupAccount) Reset() { *m = EventCreateGroupAccount{} } +func (m *EventCreateGroupAccount) String() string { return proto.CompactTextString(m) } +func (*EventCreateGroupAccount) ProtoMessage() {} +func (*EventCreateGroupAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{2} +} +func (m *EventCreateGroupAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventCreateGroupAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventCreateGroupAccount.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 *EventCreateGroupAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventCreateGroupAccount.Merge(m, src) +} +func (m *EventCreateGroupAccount) XXX_Size() int { + return m.Size() +} +func (m *EventCreateGroupAccount) XXX_DiscardUnknown() { + xxx_messageInfo_EventCreateGroupAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_EventCreateGroupAccount proto.InternalMessageInfo + +func (m *EventCreateGroupAccount) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +// EventUpdateGroupAccount is an event emitted when a group account is updated. +type EventUpdateGroupAccount struct { + // address is the address of the group account. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *EventUpdateGroupAccount) Reset() { *m = EventUpdateGroupAccount{} } +func (m *EventUpdateGroupAccount) String() string { return proto.CompactTextString(m) } +func (*EventUpdateGroupAccount) ProtoMessage() {} +func (*EventUpdateGroupAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{3} +} +func (m *EventUpdateGroupAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventUpdateGroupAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventUpdateGroupAccount.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 *EventUpdateGroupAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventUpdateGroupAccount.Merge(m, src) +} +func (m *EventUpdateGroupAccount) XXX_Size() int { + return m.Size() +} +func (m *EventUpdateGroupAccount) XXX_DiscardUnknown() { + xxx_messageInfo_EventUpdateGroupAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_EventUpdateGroupAccount proto.InternalMessageInfo + +func (m *EventUpdateGroupAccount) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +// EventCreateProposal is an event emitted when a proposal is created. +type EventCreateProposal struct { + // proposal_id is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *EventCreateProposal) Reset() { *m = EventCreateProposal{} } +func (m *EventCreateProposal) String() string { return proto.CompactTextString(m) } +func (*EventCreateProposal) ProtoMessage() {} +func (*EventCreateProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{4} +} +func (m *EventCreateProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventCreateProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventCreateProposal.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 *EventCreateProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventCreateProposal.Merge(m, src) +} +func (m *EventCreateProposal) XXX_Size() int { + return m.Size() +} +func (m *EventCreateProposal) XXX_DiscardUnknown() { + xxx_messageInfo_EventCreateProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_EventCreateProposal proto.InternalMessageInfo + +func (m *EventCreateProposal) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +// EventVote is an event emitted when a voter votes on a proposal. +type EventVote struct { + // proposal_id is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *EventVote) Reset() { *m = EventVote{} } +func (m *EventVote) String() string { return proto.CompactTextString(m) } +func (*EventVote) ProtoMessage() {} +func (*EventVote) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{5} +} +func (m *EventVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventVote.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 *EventVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventVote.Merge(m, src) +} +func (m *EventVote) XXX_Size() int { + return m.Size() +} +func (m *EventVote) XXX_DiscardUnknown() { + xxx_messageInfo_EventVote.DiscardUnknown(m) +} + +var xxx_messageInfo_EventVote proto.InternalMessageInfo + +func (m *EventVote) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +// EventExec is an event emitted when a proposal is executed. +type EventExec struct { + // proposal_id is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *EventExec) Reset() { *m = EventExec{} } +func (m *EventExec) String() string { return proto.CompactTextString(m) } +func (*EventExec) ProtoMessage() {} +func (*EventExec) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{6} +} +func (m *EventExec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventExec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventExec.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 *EventExec) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventExec.Merge(m, src) +} +func (m *EventExec) XXX_Size() int { + return m.Size() +} +func (m *EventExec) XXX_DiscardUnknown() { + xxx_messageInfo_EventExec.DiscardUnknown(m) +} + +var xxx_messageInfo_EventExec proto.InternalMessageInfo + +func (m *EventExec) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +// EventCreateProposal is an event emitted when a proposal is created. +type EventCreatePoll struct { + // poll_id is the unique ID of the poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` +} + +func (m *EventCreatePoll) Reset() { *m = EventCreatePoll{} } +func (m *EventCreatePoll) String() string { return proto.CompactTextString(m) } +func (*EventCreatePoll) ProtoMessage() {} +func (*EventCreatePoll) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{7} +} +func (m *EventCreatePoll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventCreatePoll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventCreatePoll.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 *EventCreatePoll) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventCreatePoll.Merge(m, src) +} +func (m *EventCreatePoll) XXX_Size() int { + return m.Size() +} +func (m *EventCreatePoll) XXX_DiscardUnknown() { + xxx_messageInfo_EventCreatePoll.DiscardUnknown(m) +} + +var xxx_messageInfo_EventCreatePoll proto.InternalMessageInfo + +func (m *EventCreatePoll) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +// EventVotePoll is an event emitted when a voter votes on a proposal. +type EventVotePoll struct { + // poll_id is the unique ID of the proposal. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` +} + +func (m *EventVotePoll) Reset() { *m = EventVotePoll{} } +func (m *EventVotePoll) String() string { return proto.CompactTextString(m) } +func (*EventVotePoll) ProtoMessage() {} +func (*EventVotePoll) Descriptor() ([]byte, []int) { + return fileDescriptor_3545d78da3f76a06, []int{8} +} +func (m *EventVotePoll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *EventVotePoll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_EventVotePoll.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 *EventVotePoll) XXX_Merge(src proto.Message) { + xxx_messageInfo_EventVotePoll.Merge(m, src) +} +func (m *EventVotePoll) XXX_Size() int { + return m.Size() +} +func (m *EventVotePoll) XXX_DiscardUnknown() { + xxx_messageInfo_EventVotePoll.DiscardUnknown(m) +} + +var xxx_messageInfo_EventVotePoll proto.InternalMessageInfo + +func (m *EventVotePoll) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func init() { + proto.RegisterType((*EventCreateGroup)(nil), "regen.group.v1alpha1.EventCreateGroup") + proto.RegisterType((*EventUpdateGroup)(nil), "regen.group.v1alpha1.EventUpdateGroup") + proto.RegisterType((*EventCreateGroupAccount)(nil), "regen.group.v1alpha1.EventCreateGroupAccount") + proto.RegisterType((*EventUpdateGroupAccount)(nil), "regen.group.v1alpha1.EventUpdateGroupAccount") + proto.RegisterType((*EventCreateProposal)(nil), "regen.group.v1alpha1.EventCreateProposal") + proto.RegisterType((*EventVote)(nil), "regen.group.v1alpha1.EventVote") + proto.RegisterType((*EventExec)(nil), "regen.group.v1alpha1.EventExec") + proto.RegisterType((*EventCreatePoll)(nil), "regen.group.v1alpha1.EventCreatePoll") + proto.RegisterType((*EventVotePoll)(nil), "regen.group.v1alpha1.EventVotePoll") +} + +func init() { proto.RegisterFile("regen/group/v1alpha1/events.proto", fileDescriptor_3545d78da3f76a06) } + +var fileDescriptor_3545d78da3f76a06 = []byte{ + // 287 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x2c, 0x4a, 0x4d, 0x4f, + 0xcd, 0xd3, 0x4f, 0x2f, 0xca, 0x2f, 0x2d, 0xd0, 0x2f, 0x33, 0x4c, 0xcc, 0x29, 0xc8, 0x48, 0x34, + 0xd4, 0x4f, 0x2d, 0x4b, 0xcd, 0x2b, 0x29, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x01, + 0x2b, 0xd1, 0x03, 0x2b, 0xd1, 0x83, 0x29, 0x51, 0xd2, 0xe5, 0x12, 0x70, 0x05, 0xa9, 0x72, 0x2e, + 0x4a, 0x4d, 0x2c, 0x49, 0x75, 0x07, 0x49, 0x0a, 0x49, 0x72, 0x71, 0x80, 0x55, 0xc5, 0x67, 0xa6, + 0x48, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x04, 0xb1, 0x83, 0xf9, 0x9e, 0x29, 0x70, 0xe5, 0xa1, 0x05, + 0x29, 0xc4, 0x28, 0x37, 0xe6, 0x12, 0x47, 0x37, 0xdd, 0x31, 0x39, 0x39, 0xbf, 0x34, 0xaf, 0x44, + 0x48, 0x82, 0x8b, 0x3d, 0x31, 0x25, 0xa5, 0x28, 0xb5, 0xb8, 0x18, 0xac, 0x89, 0x33, 0x08, 0xc6, + 0x85, 0x6b, 0x42, 0xb2, 0x83, 0xb0, 0x26, 0x33, 0x2e, 0x61, 0x24, 0x9b, 0x02, 0x8a, 0xf2, 0x0b, + 0xf2, 0x8b, 0x13, 0x73, 0x84, 0xe4, 0xb9, 0xb8, 0x0b, 0xa0, 0x6c, 0x84, 0xf3, 0xb8, 0x60, 0x42, + 0x9e, 0x29, 0x4a, 0x3a, 0x5c, 0x9c, 0x60, 0x7d, 0x61, 0xf9, 0x25, 0xa9, 0xc4, 0xab, 0x76, 0xad, + 0x48, 0x4d, 0x26, 0xac, 0x5a, 0x8b, 0x8b, 0x1f, 0xd9, 0x4d, 0xf9, 0x39, 0x39, 0x42, 0xe2, 0x5c, + 0xec, 0x05, 0xf9, 0x39, 0x48, 0xea, 0xd9, 0x40, 0x5c, 0xcf, 0x14, 0x25, 0x0d, 0x2e, 0x5e, 0xb8, + 0x3b, 0xf0, 0xaa, 0x74, 0xb2, 0x3b, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, + 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x28, + 0x95, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0xe4, 0xfc, 0xe2, 0xdc, + 0xfc, 0x62, 0x28, 0xa5, 0x5b, 0x9c, 0x92, 0xad, 0x5f, 0x01, 0x49, 0x1d, 0x49, 0x6c, 0xe0, 0xe4, + 0x60, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x48, 0x73, 0xd9, 0x89, 0x33, 0x02, 0x00, 0x00, +} + +func (m *EventCreateGroup) 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 *EventCreateGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventCreateGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GroupId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EventUpdateGroup) 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 *EventUpdateGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventUpdateGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GroupId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EventCreateGroupAccount) 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 *EventCreateGroupAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventCreateGroupAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventUpdateGroupAccount) 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 *EventUpdateGroupAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventUpdateGroupAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *EventCreateProposal) 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 *EventCreateProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventCreateProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EventVote) 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 *EventVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EventExec) 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 *EventExec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventExec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EventCreatePoll) 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 *EventCreatePoll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventCreatePoll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PollId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *EventVotePoll) 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 *EventVotePoll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *EventVotePoll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PollId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintEvents(dAtA []byte, offset int, v uint64) int { + offset -= sovEvents(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *EventCreateGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovEvents(uint64(m.GroupId)) + } + return n +} + +func (m *EventUpdateGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovEvents(uint64(m.GroupId)) + } + return n +} + +func (m *EventCreateGroupAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventUpdateGroupAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + return n +} + +func (m *EventCreateProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovEvents(uint64(m.ProposalId)) + } + return n +} + +func (m *EventVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovEvents(uint64(m.ProposalId)) + } + return n +} + +func (m *EventExec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovEvents(uint64(m.ProposalId)) + } + return n +} + +func (m *EventCreatePoll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovEvents(uint64(m.PollId)) + } + return n +} + +func (m *EventVotePoll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovEvents(uint64(m.PollId)) + } + return n +} + +func sovEvents(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozEvents(x uint64) (n int) { + return sovEvents(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *EventCreateGroup) 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 ErrIntOverflowEvents + } + 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: EventCreateGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventCreateGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventUpdateGroup) 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 ErrIntOverflowEvents + } + 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: EventUpdateGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventUpdateGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventCreateGroupAccount) 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 ErrIntOverflowEvents + } + 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: EventCreateGroupAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventCreateGroupAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventUpdateGroupAccount) 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 ErrIntOverflowEvents + } + 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: EventUpdateGroupAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventUpdateGroupAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventCreateProposal) 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 ErrIntOverflowEvents + } + 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: EventCreateProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventCreateProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventVote) 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 ErrIntOverflowEvents + } + 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: EventVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventExec) 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 ErrIntOverflowEvents + } + 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: EventExec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventExec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventCreatePoll) 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 ErrIntOverflowEvents + } + 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: EventCreatePoll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventCreatePoll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *EventVotePoll) 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 ErrIntOverflowEvents + } + 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: EventVotePoll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: EventVotePoll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipEvents(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvents + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvents + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowEvents + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthEvents + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupEvents + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthEvents + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthEvents = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowEvents = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupEvents = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/group/exported/expected_keepers.go b/x/group/exported/expected_keepers.go new file mode 100644 index 0000000000..47a8f6a31b --- /dev/null +++ b/x/group/exported/expected_keepers.go @@ -0,0 +1,24 @@ +package exported + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +type AccountKeeper interface { + GetParams(ctx sdk.Context) (params authtypes.Params) + + // Return a new account with the next account number. Does not save the new account to the store. + NewAccount(sdk.Context, authtypes.AccountI) authtypes.AccountI + + // Retrieve an account from the store. + GetAccount(sdk.Context, sdk.AccAddress) authtypes.AccountI + + // Set an account in the store. + SetAccount(sdk.Context, authtypes.AccountI) +} + +// BankKeeper defines the expected interface needed to retrieve account balances. +type BankKeeper interface { + SpendableCoins(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins +} diff --git a/x/group/genesis.go b/x/group/genesis.go new file mode 100644 index 0000000000..53c25888ed --- /dev/null +++ b/x/group/genesis.go @@ -0,0 +1,29 @@ +package group + +import "github.com/cosmos/cosmos-sdk/codec/types" + +// NewGenesisState creates a new genesis state with default values. +func NewGenesisState() *GenesisState { + return &GenesisState{} +} + +func (s GenesisState) Validate() error { + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (s GenesisState) UnpackInterfaces(unpacker types.AnyUnpacker) error { + for _, g := range s.GroupAccounts { + err := g.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + for _, p := range s.Proposals { + err := p.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + return nil +} diff --git a/x/group/genesis.pb.go b/x/group/genesis.pb.go new file mode 100644 index 0000000000..b7fd4bf8c2 --- /dev/null +++ b/x/group/genesis.pb.go @@ -0,0 +1,872 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: regen/group/v1alpha1/genesis.proto + +package group + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// GenesisState defines the group module's genesis state. +type GenesisState struct { + // group_seq is the group table orm.Sequence, + // it is used to get the next group ID. + GroupSeq uint64 `protobuf:"varint,1,opt,name=group_seq,json=groupSeq,proto3" json:"group_seq,omitempty"` + // groups is the list of groups info. + Groups []*GroupInfo `protobuf:"bytes,2,rep,name=groups,proto3" json:"groups,omitempty"` + // group_members is the list of groups members. + GroupMembers []*GroupMember `protobuf:"bytes,3,rep,name=group_members,json=groupMembers,proto3" json:"group_members,omitempty"` + // group_account_seq is the group account table orm.Sequence, + // it is used to generate the next group account address. + GroupAccountSeq uint64 `protobuf:"varint,4,opt,name=group_account_seq,json=groupAccountSeq,proto3" json:"group_account_seq,omitempty"` + // group_accounts is the list of group accounts info. + GroupAccounts []*GroupAccountInfo `protobuf:"bytes,5,rep,name=group_accounts,json=groupAccounts,proto3" json:"group_accounts,omitempty"` + // proposal_seq is the proposal table orm.Sequence, + // it is used to get the next proposal ID. + ProposalSeq uint64 `protobuf:"varint,6,opt,name=proposal_seq,json=proposalSeq,proto3" json:"proposal_seq,omitempty"` + // proposals is the list of proposals. + Proposals []*Proposal `protobuf:"bytes,7,rep,name=proposals,proto3" json:"proposals,omitempty"` + // votes is the list of votes. + Votes []*Vote `protobuf:"bytes,8,rep,name=votes,proto3" json:"votes,omitempty"` + // polls is the list of polls. + Polls []*Poll `protobuf:"bytes,9,rep,name=polls,proto3" json:"polls,omitempty"` + // poll_seq is the poll table orm.Sequence, + // it is used to get the next poll ID. + PollSeq uint64 `protobuf:"varint,10,opt,name=poll_seq,json=pollSeq,proto3" json:"poll_seq,omitempty"` + // votes is the list of votes for poll. + VotesForPoll []*VotePoll `protobuf:"bytes,11,rep,name=votes_for_poll,json=votesForPoll,proto3" json:"votes_for_poll,omitempty"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_6ccc5d002e96a4ab, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.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 *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetGroupSeq() uint64 { + if m != nil { + return m.GroupSeq + } + return 0 +} + +func (m *GenesisState) GetGroups() []*GroupInfo { + if m != nil { + return m.Groups + } + return nil +} + +func (m *GenesisState) GetGroupMembers() []*GroupMember { + if m != nil { + return m.GroupMembers + } + return nil +} + +func (m *GenesisState) GetGroupAccountSeq() uint64 { + if m != nil { + return m.GroupAccountSeq + } + return 0 +} + +func (m *GenesisState) GetGroupAccounts() []*GroupAccountInfo { + if m != nil { + return m.GroupAccounts + } + return nil +} + +func (m *GenesisState) GetProposalSeq() uint64 { + if m != nil { + return m.ProposalSeq + } + return 0 +} + +func (m *GenesisState) GetProposals() []*Proposal { + if m != nil { + return m.Proposals + } + return nil +} + +func (m *GenesisState) GetVotes() []*Vote { + if m != nil { + return m.Votes + } + return nil +} + +func (m *GenesisState) GetPolls() []*Poll { + if m != nil { + return m.Polls + } + return nil +} + +func (m *GenesisState) GetPollSeq() uint64 { + if m != nil { + return m.PollSeq + } + return 0 +} + +func (m *GenesisState) GetVotesForPoll() []*VotePoll { + if m != nil { + return m.VotesForPoll + } + return nil +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "regen.group.v1alpha1.GenesisState") +} + +func init() { + proto.RegisterFile("regen/group/v1alpha1/genesis.proto", fileDescriptor_6ccc5d002e96a4ab) +} + +var fileDescriptor_6ccc5d002e96a4ab = []byte{ + // 408 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcd, 0xaa, 0xda, 0x40, + 0x14, 0xc7, 0x4d, 0xfd, 0x1e, 0xa3, 0xa5, 0x83, 0x8b, 0xa9, 0x85, 0x54, 0xa5, 0x14, 0x29, 0x34, + 0xa9, 0xed, 0xa2, 0x9b, 0x52, 0x68, 0x29, 0x4a, 0x17, 0x82, 0x44, 0xe8, 0xa2, 0x1b, 0x89, 0xe9, + 0x18, 0xa5, 0x49, 0x4e, 0xcc, 0x8c, 0xd2, 0xbe, 0x45, 0x1f, 0xab, 0x9b, 0x0b, 0x2e, 0xef, 0xf2, + 0xa2, 0x2f, 0x72, 0x99, 0x33, 0x11, 0xef, 0x85, 0x90, 0x55, 0xe6, 0x9c, 0xfc, 0xfe, 0x1f, 0x03, + 0x43, 0x86, 0x29, 0x0f, 0x78, 0xec, 0x04, 0x29, 0xec, 0x13, 0xe7, 0x30, 0xf6, 0xc2, 0x64, 0xe3, + 0x8d, 0x9d, 0x80, 0xc7, 0x5c, 0x6c, 0x85, 0x9d, 0xa4, 0x20, 0x81, 0x76, 0x91, 0xb1, 0x91, 0xb1, + 0x2f, 0x4c, 0xaf, 0x1b, 0x40, 0x00, 0x08, 0x38, 0xea, 0xa4, 0xd9, 0x5e, 0x3f, 0xd7, 0x4f, 0xfe, + 0x4d, 0x78, 0xe6, 0x36, 0xbc, 0xa9, 0x10, 0x73, 0xaa, 0xfd, 0x17, 0xd2, 0x93, 0x9c, 0xbe, 0x20, + 0x4d, 0xc4, 0x97, 0x82, 0xef, 0x98, 0xd1, 0x37, 0x46, 0x15, 0xb7, 0x81, 0x8b, 0x05, 0xdf, 0xd1, + 0x8f, 0xa4, 0x86, 0x67, 0xc1, 0x9e, 0xf4, 0xcb, 0xa3, 0xd6, 0xfb, 0x97, 0x76, 0x5e, 0x19, 0x7b, + 0xaa, 0xc6, 0xef, 0xf1, 0x1a, 0xdc, 0x0c, 0xa7, 0x13, 0xd2, 0xd6, 0xae, 0x11, 0x8f, 0x56, 0x3c, + 0x15, 0xac, 0x8c, 0xfa, 0x41, 0x81, 0x7e, 0x86, 0xa4, 0x6b, 0x06, 0xd7, 0x41, 0xd0, 0x37, 0xe4, + 0x99, 0xf6, 0xf1, 0x7c, 0x1f, 0xf6, 0xb1, 0xc4, 0x96, 0x15, 0x6c, 0xf9, 0x14, 0x7f, 0x7c, 0xd1, + 0x7b, 0x55, 0x76, 0x46, 0x3a, 0x8f, 0x58, 0xc1, 0xaa, 0x18, 0xfa, 0xba, 0x20, 0x34, 0x93, 0x63, + 0xf7, 0xf6, 0x43, 0x43, 0x41, 0x07, 0xc4, 0x4c, 0x52, 0x48, 0x40, 0x78, 0x21, 0xa6, 0xd6, 0x30, + 0xb5, 0x75, 0xd9, 0xa9, 0xc4, 0x4f, 0xa4, 0x79, 0x19, 0x05, 0xab, 0x63, 0x98, 0x95, 0x1f, 0x36, + 0xcf, 0x30, 0xf7, 0x2a, 0xa0, 0xef, 0x48, 0xf5, 0x00, 0x92, 0x0b, 0xd6, 0x40, 0x65, 0x2f, 0x5f, + 0xf9, 0x03, 0x24, 0x77, 0x35, 0xa8, 0x14, 0x09, 0x84, 0xa1, 0x60, 0xcd, 0x22, 0xc5, 0x1c, 0xc2, + 0xd0, 0xd5, 0x20, 0x7d, 0x4e, 0x1a, 0xea, 0x80, 0x17, 0x20, 0x78, 0x81, 0xba, 0x9a, 0x55, 0xf9, + 0x6f, 0xa4, 0x83, 0xae, 0xcb, 0x35, 0xa4, 0x4b, 0xb5, 0x64, 0xad, 0xa2, 0x1b, 0xa8, 0x1e, 0xe8, + 0x6c, 0xa2, 0x6a, 0x02, 0xa9, 0x9a, 0xbe, 0x7e, 0xfe, 0x7f, 0xb2, 0x8c, 0xe3, 0xc9, 0x32, 0xee, + 0x4e, 0x96, 0xf1, 0xef, 0x6c, 0x95, 0x8e, 0x67, 0xab, 0x74, 0x7b, 0xb6, 0x4a, 0x3f, 0x5f, 0x05, + 0x5b, 0xb9, 0xd9, 0xaf, 0x6c, 0x1f, 0x22, 0xc7, 0x07, 0x11, 0x81, 0xc8, 0x3e, 0x6f, 0xc5, 0xaf, + 0xdf, 0xce, 0x1f, 0xfd, 0x48, 0x57, 0x35, 0x7c, 0x96, 0x1f, 0xee, 0x03, 0x00, 0x00, 0xff, 0xff, + 0x2c, 0xd4, 0x57, 0x01, 0x0a, 0x03, 0x00, 0x00, +} + +func (m *GenesisState) 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 *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VotesForPoll) > 0 { + for iNdEx := len(m.VotesForPoll) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.VotesForPoll[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + } + } + if m.PollSeq != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.PollSeq)) + i-- + dAtA[i] = 0x50 + } + if len(m.Polls) > 0 { + for iNdEx := len(m.Polls) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Polls[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + } + } + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + } + if len(m.Proposals) > 0 { + for iNdEx := len(m.Proposals) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Proposals[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + } + } + if m.ProposalSeq != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.ProposalSeq)) + i-- + dAtA[i] = 0x30 + } + if len(m.GroupAccounts) > 0 { + for iNdEx := len(m.GroupAccounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.GroupAccounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + } + if m.GroupAccountSeq != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.GroupAccountSeq)) + i-- + dAtA[i] = 0x20 + } + if len(m.GroupMembers) > 0 { + for iNdEx := len(m.GroupMembers) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.GroupMembers[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.Groups) > 0 { + for iNdEx := len(m.Groups) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Groups[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.GroupSeq != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.GroupSeq)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupSeq != 0 { + n += 1 + sovGenesis(uint64(m.GroupSeq)) + } + if len(m.Groups) > 0 { + for _, e := range m.Groups { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.GroupMembers) > 0 { + for _, e := range m.GroupMembers { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.GroupAccountSeq != 0 { + n += 1 + sovGenesis(uint64(m.GroupAccountSeq)) + } + if len(m.GroupAccounts) > 0 { + for _, e := range m.GroupAccounts { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.ProposalSeq != 0 { + n += 1 + sovGenesis(uint64(m.ProposalSeq)) + } + if len(m.Proposals) > 0 { + for _, e := range m.Proposals { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if len(m.Polls) > 0 { + for _, e := range m.Polls { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + if m.PollSeq != 0 { + n += 1 + sovGenesis(uint64(m.PollSeq)) + } + if len(m.VotesForPoll) > 0 { + for _, e := range m.VotesForPoll { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) 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 ErrIntOverflowGenesis + } + 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: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupSeq", wireType) + } + m.GroupSeq = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupSeq |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Groups = append(m.Groups, &GroupInfo{}) + if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupMembers", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GroupMembers = append(m.GroupMembers, &GroupMember{}) + if err := m.GroupMembers[len(m.GroupMembers)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupAccountSeq", wireType) + } + m.GroupAccountSeq = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupAccountSeq |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupAccounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GroupAccounts = append(m.GroupAccounts, &GroupAccountInfo{}) + if err := m.GroupAccounts[len(m.GroupAccounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalSeq", wireType) + } + m.ProposalSeq = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalSeq |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposals", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposals = append(m.Proposals, &Proposal{}) + if err := m.Proposals[len(m.Proposals)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, &Vote{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Polls", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Polls = append(m.Polls, &Poll{}) + if err := m.Polls[len(m.Polls)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollSeq", wireType) + } + m.PollSeq = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollSeq |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VotesForPoll", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VotesForPoll = append(m.VotesForPoll, &VotePoll{}) + if err := m.VotesForPoll[len(m.VotesForPoll)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/group/keys.go b/x/group/keys.go new file mode 100644 index 0000000000..1aed1a30de --- /dev/null +++ b/x/group/keys.go @@ -0,0 +1,11 @@ +package group + +const ( + // ModuleName is the module name constant used in many places + ModuleName = "group" + + // StoreKey defines the primary module store key + StoreKey = ModuleName + + DefaultParamspace = ModuleName +) diff --git a/x/group/module/module.go b/x/group/module/module.go new file mode 100644 index 0000000000..8b01fb75a9 --- /dev/null +++ b/x/group/module/module.go @@ -0,0 +1,113 @@ +package module + +import ( + "context" + "encoding/json" + "fmt" + "math/rand" + + sdkclient "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + climodule "github.com/cosmos/cosmos-sdk/regen/types/module/client/cli" + restmodule "github.com/cosmos/cosmos-sdk/regen/types/module/client/grpc_gateway" + servermodule "github.com/cosmos/cosmos-sdk/regen/types/module/server" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/client" + "github.com/cosmos/cosmos-sdk/x/group/exported" + "github.com/cosmos/cosmos-sdk/x/group/server" + "github.com/cosmos/cosmos-sdk/x/group/simulation" + "github.com/gorilla/mux" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" +) + +type Module struct { + Registry types.InterfaceRegistry + BankKeeper exported.BankKeeper + AccountKeeper exported.AccountKeeper +} + +var _ module.AppModuleBasic = Module{} +var _ module.AppModuleSimulation = Module{} +var _ servermodule.Module = Module{} +var _ restmodule.Module = Module{} +var _ climodule.Module = Module{} + +func (a Module) Name() string { + return group.ModuleName +} + +// RegisterInterfaces registers module concrete types into protobuf Any. +func (a Module) RegisterInterfaces(registry types.InterfaceRegistry) { + group.RegisterTypes(registry) +} + +func (a Module) RegisterServices(configurator servermodule.Configurator) { + server.RegisterServices(configurator, a.AccountKeeper, a.BankKeeper) +} + +func (a Module) DefaultGenesis(marshaler codec.JSONCodec) json.RawMessage { + return marshaler.MustMarshalJSON(group.NewGenesisState()) +} + +func (a Module) ValidateGenesis(cdc codec.JSONCodec, config sdkclient.TxEncodingConfig, bz json.RawMessage) error { + var data group.GenesisState + if err := cdc.UnmarshalJSON(bz, &data); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", group.ModuleName, err) + } + return data.Validate() +} + +func (a Module) RegisterGRPCGatewayRoutes(clientCtx sdkclient.Context, mux *runtime.ServeMux) { + group.RegisterQueryHandlerClient(context.Background(), mux, group.NewQueryClient(clientCtx)) +} + +func (a Module) GetTxCmd() *cobra.Command { + return client.TxCmd(a.Name()) +} + +func (a Module) GetQueryCmd() *cobra.Command { + return client.QueryCmd(a.Name()) +} + +/**** DEPRECATED ****/ +func (a Module) RegisterRESTRoutes(sdkclient.Context, *mux.Router) {} +func (a Module) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + group.RegisterLegacyAminoCodec(cdc) +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (Module) ConsensusVersion() uint64 { return 1 } + +// AppModuleSimulation functions + +// GenerateGenesisState creates a randomized GenesisState of the group module. +func (Module) GenerateGenesisState(simState *module.SimulationState) { + simulation.RandomizedGenState(simState) +} + +// ProposalContents returns all the group content functions used to +// simulate proposals. +func (Module) ProposalContents(simState module.SimulationState) []simtypes.WeightedProposalContent { + return nil +} + +// RandomizedParams creates randomized group param changes for the simulator. +func (Module) RandomizedParams(r *rand.Rand) []simtypes.ParamChange { + return nil +} + +// RegisterStoreDecoder registers a decoder for group module's types +func (Module) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { +} + +// WeightedOperations returns all the group module operations with their respective weights. +// NOTE: This is no longer needed for the modules which uses ADR-33, group module `WeightedOperations` +// registered in the `x/group/server` package. +func (Module) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + return nil +} diff --git a/x/group/msgs.go b/x/group/msgs.go new file mode 100644 index 0000000000..443141208f --- /dev/null +++ b/x/group/msgs.go @@ -0,0 +1,1191 @@ +package group + +import ( + "bytes" + "fmt" + + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/regen/types/math" + "github.com/cosmos/cosmos-sdk/regen/types/module/server" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/auth/legacy/legacytx" + proto "github.com/gogo/protobuf/proto" + prototypes "github.com/gogo/protobuf/types" +) + +var _ sdk.Msg = &MsgCreateGroup{} +var _ legacytx.LegacyMsg = &MsgCreateGroup{} + +// Route Implements Msg. +func (m MsgCreateGroup) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgCreateGroup) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgCreateGroup) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgCreateGroup. +func (m MsgCreateGroup) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgCreateGroup) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + if err := assertMetadataLength(m.Metadata, "group metadata"); err != nil { + return err + } + + members := Members{Members: m.Members} + if err := members.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "members") + } + for i := range m.Members { + member := m.Members[i] + if _, err := math.ParsePositiveDecimal(member.Weight); err != nil { + return sdkerrors.Wrap(err, "member weight") + } + } + return nil +} + +func (m Member) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Address) + if err != nil { + return sdkerrors.Wrap(err, "address") + } + if _, err := math.ParseNonNegativeDecimal(m.Weight); err != nil { + return sdkerrors.Wrap(err, "weight") + } + + if err := assertMetadataLength(m.Metadata, "member metadata"); err != nil { + return err + } + + return nil +} + +var _ sdk.Msg = &MsgUpdateGroupAdmin{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupAdmin{} + +// Route Implements Msg. +func (m MsgUpdateGroupAdmin) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgUpdateGroupAdmin) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgUpdateGroupAdmin) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgUpdateGroupAdmin. +func (m MsgUpdateGroupAdmin) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgUpdateGroupAdmin) ValidateBasic() error { + if m.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + } + + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + newAdmin, err := sdk.AccAddressFromBech32(m.NewAdmin) + if err != nil { + return sdkerrors.Wrap(err, "new admin") + } + + if admin.Equals(newAdmin) { + return sdkerrors.Wrap(ErrInvalid, "new and old admin are the same") + } + return nil +} + +func (m *MsgUpdateGroupAdmin) GetGroupID() uint64 { + return m.GroupId +} + +var _ sdk.Msg = &MsgUpdateGroupMetadata{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupMetadata{} + +// Route Implements Msg. +func (m MsgUpdateGroupMetadata) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgUpdateGroupMetadata) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgUpdateGroupMetadata) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgUpdateGroupMetadata. +func (m MsgUpdateGroupMetadata) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgUpdateGroupMetadata) ValidateBasic() error { + if m.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + + } + _, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + if err = assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + return nil +} + +func (m *MsgUpdateGroupMetadata) GetGroupID() uint64 { + return m.GroupId +} + +var _ sdk.Msg = &MsgUpdateGroupMembers{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupMembers{} + +// Route Implements Msg. +func (m MsgUpdateGroupMembers) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgUpdateGroupMembers) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgUpdateGroupMembers) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +var _ sdk.Msg = &MsgUpdateGroupMembers{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupMembers{} + +// GetSigners returns the expected signers for a MsgUpdateGroupMembers. +func (m MsgUpdateGroupMembers) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgUpdateGroupMembers) ValidateBasic() error { + if m.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + + } + _, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + if len(m.MemberUpdates) == 0 { + return sdkerrors.Wrap(ErrEmpty, "member updates") + } + members := Members{Members: m.MemberUpdates} + if err := members.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "members") + } + return nil +} + +func (m *MsgUpdateGroupMembers) GetGroupID() uint64 { + return m.GroupId +} + +var _ sdk.Msg = &MsgCreateGroupAccount{} +var _ legacytx.LegacyMsg = &MsgCreateGroupAccount{} + +// Route Implements Msg. +func (m MsgCreateGroupAccount) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgCreateGroupAccount) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgCreateGroupAccount) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgCreateGroupAccount. +func (m MsgCreateGroupAccount) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgCreateGroupAccount) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + if m.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + } + + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + + policy := m.GetDecisionPolicy() + if policy == nil { + return sdkerrors.Wrap(ErrEmpty, "decision policy") + } + + if err := policy.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "decision policy") + } + return nil +} + +var _ sdk.Msg = &MsgUpdateGroupAccountAdmin{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupAccountAdmin{} + +// Route Implements Msg. +func (m MsgUpdateGroupAccountAdmin) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgUpdateGroupAccountAdmin) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgUpdateGroupAccountAdmin) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgUpdateGroupAccountAdmin. +func (m MsgUpdateGroupAccountAdmin) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgUpdateGroupAccountAdmin) ValidateBasic() error { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + newAdmin, err := sdk.AccAddressFromBech32(m.NewAdmin) + if err != nil { + return sdkerrors.Wrap(err, "new admin") + } + + _, err = sdk.AccAddressFromBech32(m.Address) + if err != nil { + return sdkerrors.Wrap(err, "group account") + } + + if admin.Equals(newAdmin) { + return sdkerrors.Wrap(ErrInvalid, "new and old admin are the same") + } + return nil +} + +var _ sdk.Msg = &MsgUpdateGroupAccountDecisionPolicy{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupAccountDecisionPolicy{} +var _ types.UnpackInterfacesMessage = MsgUpdateGroupAccountDecisionPolicy{} + +func NewMsgUpdateGroupAccountDecisionPolicyRequest(admin sdk.AccAddress, address sdk.AccAddress, decisionPolicy DecisionPolicy) (*MsgUpdateGroupAccountDecisionPolicy, error) { + m := &MsgUpdateGroupAccountDecisionPolicy{ + Admin: admin.String(), + Address: address.String(), + } + err := m.SetDecisionPolicy(decisionPolicy) + if err != nil { + return nil, err + } + return m, nil +} + +func (m *MsgUpdateGroupAccountDecisionPolicy) SetDecisionPolicy(decisionPolicy DecisionPolicy) error { + msg, ok := decisionPolicy.(proto.Message) + if !ok { + return fmt.Errorf("can't proto marshal %T", msg) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return err + } + m.DecisionPolicy = any + return nil +} + +// Route Implements Msg. +func (m MsgUpdateGroupAccountDecisionPolicy) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgUpdateGroupAccountDecisionPolicy) Type() string { + return sdk.MsgTypeURL(&m) +} + +// GetSignBytes Implements Msg. +func (m MsgUpdateGroupAccountDecisionPolicy) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgUpdateGroupAccountDecisionPolicy. +func (m MsgUpdateGroupAccountDecisionPolicy) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgUpdateGroupAccountDecisionPolicy) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + _, err = sdk.AccAddressFromBech32(m.Address) + if err != nil { + return sdkerrors.Wrap(err, "group account") + } + + policy := m.GetDecisionPolicy() + if policy == nil { + return sdkerrors.Wrap(ErrEmpty, "decision policy") + } + + if err := policy.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "decision policy") + } + + return nil +} + +func (m *MsgUpdateGroupAccountDecisionPolicy) GetDecisionPolicy() DecisionPolicy { + decisionPolicy, ok := m.DecisionPolicy.GetCachedValue().(DecisionPolicy) + if !ok { + return nil + } + return decisionPolicy +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (m MsgUpdateGroupAccountDecisionPolicy) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var decisionPolicy DecisionPolicy + return unpacker.UnpackAny(m.DecisionPolicy, &decisionPolicy) +} + +var _ sdk.Msg = &MsgUpdateGroupAccountMetadata{} +var _ legacytx.LegacyMsg = &MsgUpdateGroupAccountMetadata{} + +// Route Implements Msg. +func (m MsgUpdateGroupAccountMetadata) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgUpdateGroupAccountMetadata) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgUpdateGroupAccountMetadata) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgUpdateGroupAccountMetadata. +func (m MsgUpdateGroupAccountMetadata) GetSigners() []sdk.AccAddress { + admin, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + panic(err) + } + return []sdk.AccAddress{admin} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgUpdateGroupAccountMetadata) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + _, err = sdk.AccAddressFromBech32(m.Address) + if err != nil { + return sdkerrors.Wrap(err, "group account") + } + + if err := assertMetadataLength(m.Metadata, "group account metadata"); err != nil { + return err + } + + return nil +} + +var _ sdk.Msg = &MsgCreateGroupAccount{} +var _ legacytx.LegacyMsg = &MsgCreateGroupAccount{} +var _ types.UnpackInterfacesMessage = MsgCreateGroupAccount{} + +// NewMsgCreateGroupAccount creates a new MsgCreateGroupAccount. +func NewMsgCreateGroupAccount(admin sdk.AccAddress, group uint64, metadata []byte, decisionPolicy DecisionPolicy) (*MsgCreateGroupAccount, error) { + m := &MsgCreateGroupAccount{ + Admin: admin.String(), + GroupId: group, + Metadata: metadata, + } + err := m.SetDecisionPolicy(decisionPolicy) + if err != nil { + return nil, err + } + return m, nil +} + +func (m *MsgCreateGroupAccount) GetAdmin() string { + return m.Admin +} + +func (m *MsgCreateGroupAccount) GetGroupID() uint64 { + return m.GroupId +} + +func (m *MsgCreateGroupAccount) GetMetadata() []byte { + return m.Metadata +} + +func (m *MsgCreateGroupAccount) GetDecisionPolicy() DecisionPolicy { + decisionPolicy, ok := m.DecisionPolicy.GetCachedValue().(DecisionPolicy) + if !ok { + return nil + } + return decisionPolicy +} + +func (m *MsgCreateGroupAccount) SetDecisionPolicy(decisionPolicy DecisionPolicy) error { + msg, ok := decisionPolicy.(proto.Message) + if !ok { + return fmt.Errorf("can't proto marshal %T", msg) + } + any, err := types.NewAnyWithValue(msg) + if err != nil { + return err + } + m.DecisionPolicy = any + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (m MsgCreateGroupAccount) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var decisionPolicy DecisionPolicy + return unpacker.UnpackAny(m.DecisionPolicy, &decisionPolicy) +} + +var _ sdk.Msg = &MsgCreateProposal{} +var _ legacytx.LegacyMsg = &MsgCreateProposal{} + +// NewMsgCreateProposalRequest creates a new MsgCreateProposal. +func NewMsgCreateProposalRequest(address string, proposers []string, msgs []sdk.Msg, metadata []byte, exec Exec) (*MsgCreateProposal, error) { + m := &MsgCreateProposal{ + Address: address, + Proposers: proposers, + Metadata: metadata, + Exec: exec, + } + err := m.SetMsgs(msgs) + if err != nil { + return nil, err + } + return m, nil +} + +// Route Implements Msg. +func (m MsgCreateProposal) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgCreateProposal) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgCreateProposal) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgCreateProposal. +func (m MsgCreateProposal) GetSigners() []sdk.AccAddress { + addrs := make([]sdk.AccAddress, len(m.Proposers)) + for i, proposer := range m.Proposers { + addr, err := sdk.AccAddressFromBech32(proposer) + if err != nil { + panic(err) + } + addrs[i] = addr + } + return addrs +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgCreateProposal) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Address) + if err != nil { + return sdkerrors.Wrap(err, "group account") + } + + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + + if len(m.Proposers) == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposers") + } + addrs := make([]sdk.AccAddress, len(m.Proposers)) + for i, proposer := range m.Proposers { + addr, err := sdk.AccAddressFromBech32(proposer) + if err != nil { + return sdkerrors.Wrap(err, "proposers") + } + addrs[i] = addr + } + if err := AccAddresses(addrs).ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proposers") + } + + msgs := m.GetMsgs() + for i, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return sdkerrors.Wrapf(err, "msg %d", i) + } + } + + return nil +} + +// SetMsgs packs msgs into Any's +func (m *MsgCreateProposal) SetMsgs(msgs []sdk.Msg) error { + anys, err := server.SetMsgs(msgs) + if err != nil { + return err + } + m.Msgs = anys + return nil +} + +// GetMsgs unpacks m.Msgs Any's into sdk.Msg's +func (m MsgCreateProposal) GetMsgs() []sdk.Msg { + msgs, err := server.GetMsgs(m.Msgs) + if err != nil { + panic(err) + } + return msgs +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (m MsgCreateProposal) UnpackInterfaces(unpacker types.AnyUnpacker) error { + return server.UnpackInterfaces(unpacker, m.Msgs) +} + +var _ sdk.Msg = &MsgVote{} +var _ legacytx.LegacyMsg = &MsgVote{} + +// Route Implements Msg. +func (m MsgVote) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVote) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVote) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgVote. +func (m MsgVote) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVote) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + return sdkerrors.Wrap(err, "voter") + } + if m.ProposalId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + if m.Choice == Choice_CHOICE_UNSPECIFIED { + return sdkerrors.Wrap(ErrEmpty, "choice") + } + if _, ok := Choice_name[int32(m.Choice)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "choice") + } + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + return nil +} + +var _ sdk.Msg = &MsgVoteBasic{} +var _ legacytx.LegacyMsg = &MsgVoteBasic{} + +// Route Implements Msg. +func (m MsgVoteBasic) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVoteBasic) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVoteBasic) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgVoteRequest. +func (m MsgVoteBasic) GetSigners() []sdk.AccAddress { + panic("this message does not include signers") +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVoteBasic) ValidateBasic() error { + if m.ProposalId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + if m.Choice == Choice_CHOICE_UNSPECIFIED { + return sdkerrors.Wrap(ErrEmpty, "choice") + } + if _, ok := Choice_name[int32(m.Choice)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "choice") + } + t, err := prototypes.TimestampFromProto(&m.Expiry) + if err != nil { + return sdkerrors.Wrap(err, "vote expiry") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "vote expiry") + } + return nil +} + +var _ sdk.Msg = &MsgVoteBasicResponse{} +var _ legacytx.LegacyMsg = &MsgVoteBasicResponse{} +var _ types.UnpackInterfacesMessage = MsgVoteBasicResponse{} + +// Route Implements Msg. +func (m MsgVoteBasicResponse) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVoteBasicResponse) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVoteBasicResponse) GetSignBytes() []byte { + res := MsgVoteBasic{ + ProposalId: m.ProposalId, + Choice: m.Choice, + Expiry: m.Expiry, + } + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&res)) +} + +// GetSigners returns the expected signers for a MsgVoteRequest. +func (m MsgVoteBasicResponse) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVoteBasicResponse) ValidateBasic() error { + if m.ProposalId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + + if m.Choice == Choice_CHOICE_UNSPECIFIED { + return sdkerrors.Wrap(ErrEmpty, "choice") + } + if _, ok := Choice_name[int32(m.Choice)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "choice") + } + + _, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + return sdkerrors.Wrap(err, "voter account") + } + + if m.PubKey == nil { + return sdkerrors.Wrap(ErrEmpty, "public key") + } + + if len(m.Sig) == 0 { + return sdkerrors.Wrap(ErrEmpty, "voter signature") + } + + t, err := prototypes.TimestampFromProto(&m.Expiry) + if err != nil { + return sdkerrors.Wrap(err, "expiry") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "expiry") + } + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (m MsgVoteBasicResponse) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var pk cryptotypes.PubKey + return unpacker.UnpackAny(m.PubKey, &pk) +} + +func (m MsgVoteBasicResponse) VerifySignature() error { + msgBytes := m.GetSignBytes() + voterAddress := m.GetSigners()[0] + + pubKey, ok := m.PubKey.GetCachedValue().(cryptotypes.PubKey) + if !ok { + return sdkerrors.Wrap(ErrInvalid, "public key") + } + + if !bytes.Equal(pubKey.Address(), voterAddress) { + return sdkerrors.Wrapf(ErrInvalid, "public key does not match the voter's address %s", m.Voter) + } + + if !pubKey.VerifySignature(msgBytes, m.Sig) { + return sdkerrors.Wrap(ErrInvalid, "sigature verification failed") + } + + return nil +} + +var _ sdk.Msg = &MsgVoteAgg{} +var _ legacytx.LegacyMsg = &MsgVoteAgg{} + +// Route Implements Msg. +func (m MsgVoteAgg) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVoteAgg) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVoteAgg) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgVoteRequest. +func (m MsgVoteAgg) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVoteAgg) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Sender) + if err != nil { + return sdkerrors.Wrap(err, "sender") + } + + if m.ProposalId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + + if len(m.Votes) == 0 { + return sdkerrors.Wrap(ErrEmpty, "votes") + } + for _, c := range m.Votes { + if _, ok := Choice_name[int32(c)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "choice") + } + } + + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + + if len(m.AggSig) == 0 { + return sdkerrors.Wrap(ErrEmpty, "voter signature") + } + + t, err := prototypes.TimestampFromProto(&m.Expiry) + if err != nil { + return sdkerrors.Wrap(err, "expiry") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "expiry") + } + return nil +} + +var _ sdk.Msg = &MsgExec{} +var _ legacytx.LegacyMsg = &MsgExec{} + +// Route Implements Msg. +func (m MsgExec) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgExec) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgExec) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgExec. +func (m MsgExec) GetSigners() []sdk.AccAddress { + signer, err := sdk.AccAddressFromBech32(m.Signer) + if err != nil { + panic(err) + } + return []sdk.AccAddress{signer} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgExec) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Signer) + if err != nil { + return sdkerrors.Wrap(err, "signer") + } + if m.ProposalId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + return nil +} + +var _ sdk.Msg = &MsgCreatePoll{} +var _ legacytx.LegacyMsg = &MsgCreatePoll{} + +// Route Implements Msg. +func (m MsgCreatePoll) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgCreatePoll) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgCreatePoll) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgCreateProposal. +func (m MsgCreatePoll) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Creator) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgCreatePoll) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Creator) + if err != nil { + return sdkerrors.Wrap(err, "creator account") + } + + if m.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + } + + if len(m.Title) == 0 { + return sdkerrors.Wrap(ErrEmpty, "poll title") + } + + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + if err := assertTitleLength(m.Title, "poll title"); err != nil { + return err + } + + if err := m.Options.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "options") + } + + if m.VoteLimit <= 0 { + return sdkerrors.Wrap(ErrInvalid, "vote limit must be positive") + } + + if int(m.VoteLimit) > len(m.Options.Titles) { + return sdkerrors.Wrap(ErrInvalid, "vote limit exceeds the number of options") + } + + t, err := prototypes.TimestampFromProto(&m.Timeout) + if err != nil { + return sdkerrors.Wrap(err, "timeout") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "timeout") + } + + return nil +} + +var _ sdk.Msg = &MsgVotePoll{} +var _ legacytx.LegacyMsg = &MsgVotePoll{} + +// Route Implements Msg. +func (m MsgVotePoll) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVotePoll) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVotePoll) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgCreateProposal. +func (m MsgVotePoll) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVotePoll) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + return sdkerrors.Wrap(err, "creator account") + } + + if m.PollId == 0 { + return sdkerrors.Wrap(ErrEmpty, "poll") + } + + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + + if err := m.Options.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "options") + } + + return nil +} + +var _ sdk.Msg = &MsgVotePollBasic{} +var _ legacytx.LegacyMsg = &MsgVotePollBasic{} + +// Route Implements Msg. +func (m MsgVotePollBasic) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVotePollBasic) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVotePollBasic) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgCreateProposal. +func (m MsgVotePollBasic) GetSigners() []sdk.AccAddress { + panic("not implemented for this message") +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVotePollBasic) ValidateBasic() error { + if m.PollId == 0 { + return sdkerrors.Wrap(ErrEmpty, "poll") + } + + if len(m.Option) == 0 { + return sdkerrors.Wrap(ErrEmpty, "vote option") + } + + t, err := prototypes.TimestampFromProto(&m.Expiry) + if err != nil { + return sdkerrors.Wrap(err, "vote expiry") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "vote expiry") + } + return nil +} + +var _ sdk.Msg = &MsgVotePollBasicResponse{} +var _ legacytx.LegacyMsg = &MsgVotePollBasicResponse{} +var _ types.UnpackInterfacesMessage = MsgVotePollBasicResponse{} + +// Route Implements Msg. +func (m MsgVotePollBasicResponse) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVotePollBasicResponse) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVotePollBasicResponse) GetSignBytes() []byte { + panic("not implemented") +} + +func (m MsgVotePollBasicResponse) GetSignBytesMany() [][]byte { + signBytesMany := make([][]byte, 0, len(m.Options.Titles)) + for _, x := range m.Options.Titles { + y := MsgVotePollBasic{ + PollId: m.PollId, + Option: x, + Expiry: m.Expiry, + } + signBytesMany = append(signBytesMany, y.GetSignBytes()) + } + return signBytesMany +} + +// GetSigners returns the expected signers for a MsgVoteRequest. +func (m MsgVotePollBasicResponse) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVotePollBasicResponse) ValidateBasic() error { + if m.PollId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + if err := m.Options.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "options") + } + _, err := sdk.AccAddressFromBech32(m.Voter) + if err != nil { + return sdkerrors.Wrap(err, "voter account") + } + if m.PubKey == nil { + return sdkerrors.Wrap(ErrEmpty, "public key") + } + if len(m.Sig) == 0 { + return sdkerrors.Wrap(ErrEmpty, "voter signature") + } + t, err := prototypes.TimestampFromProto(&m.Expiry) + if err != nil { + return sdkerrors.Wrap(err, "expiry") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "expiry") + } + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (m MsgVotePollBasicResponse) UnpackInterfaces(unpacker types.AnyUnpacker) error { + var pk cryptotypes.PubKey + return unpacker.UnpackAny(m.PubKey, &pk) +} + +func (m MsgVotePollBasicResponse) VerifySignature() error { + msgsBytes := m.GetSignBytesMany() + voterAddress := m.GetSigners()[0] + + pubKey, ok := m.PubKey.GetCachedValue().(cryptotypes.PubKey) + if !ok { + return sdkerrors.Wrap(ErrInvalid, "public key") + } + + if !bytes.Equal(pubKey.Address(), voterAddress) { + return sdkerrors.Wrapf(ErrInvalid, "public key does not match the voter's address %s", m.Voter) + } + + pkBls, ok := pubKey.(*bls12381.PubKey) + if !ok { + return fmt.Errorf("only support bls public key") + } + + // todo: repeated public keys can be coalesced in pairings + var pkss [][]*bls12381.PubKey + for _ = range m.Options.Titles { + pkss = append(pkss, []*bls12381.PubKey{pkBls}) + } + + if err := bls12381.VerifyAggregateSignature(msgsBytes, false, m.Sig, pkss); err != nil { + return err + } + + return nil +} + +var _ sdk.Msg = &MsgVotePollAgg{} +var _ legacytx.LegacyMsg = &MsgVotePollAgg{} + +// Route Implements Msg. +func (m MsgVotePollAgg) Route() string { return sdk.MsgTypeURL(&m) } + +// Type Implements Msg. +func (m MsgVotePollAgg) Type() string { return sdk.MsgTypeURL(&m) } + +// GetSignBytes Implements Msg. +func (m MsgVotePollAgg) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +// GetSigners returns the expected signers for a MsgVoteRequest. +func (m MsgVotePollAgg) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Sender) + if err != nil { + panic(err) + } + return []sdk.AccAddress{addr} +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgVotePollAgg) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Sender) + if err != nil { + return sdkerrors.Wrap(err, "sender") + } + if m.PollId == 0 { + return sdkerrors.Wrap(ErrEmpty, "poll") + } + if len(m.Votes) == 0 { + return sdkerrors.Wrap(ErrEmpty, "votes") + } + for _, v := range m.Votes { + if len(v.Titles) != 0 { + if err := v.ValidateBasic(); err != nil { + return sdkerrors.Wrap(ErrInvalid, "options") + } + } + } + if err := assertMetadataLength(m.Metadata, "metadata"); err != nil { + return err + } + if len(m.AggSig) == 0 { + return sdkerrors.Wrap(ErrEmpty, "signature") + } + t, err := prototypes.TimestampFromProto(&m.Expiry) + if err != nil { + return sdkerrors.Wrap(err, "expiry") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "expiry") + } + return nil +} diff --git a/x/group/msgs_test.go b/x/group/msgs_test.go new file mode 100644 index 0000000000..6963b59411 --- /dev/null +++ b/x/group/msgs_test.go @@ -0,0 +1,1048 @@ +package group + +import ( + "bytes" + "fmt" + "strings" + "testing" + "time" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + gogotypes "github.com/gogo/protobuf/types" + proto "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestMsgCreateGroupValidation(t *testing.T) { + _, _, myAddr := testdata.KeyTestPubAddr() + _, _, myOtherAddr := testdata.KeyTestPubAddr() + + specs := map[string]struct { + src MsgCreateGroup + expErr bool + }{ + "all good with minimum fields set": { + src: MsgCreateGroup{Admin: myAddr.String()}, + }, + "all good with a member": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Address: myAddr.String(), Weight: "1"}, + }, + }, + }, + "all good with multiple members": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Address: myAddr.String(), Weight: "1"}, + {Address: myOtherAddr.String(), Weight: "2"}, + }, + }, + }, + "admin required": { + src: MsgCreateGroup{}, + expErr: true, + }, + "valid admin required": { + src: MsgCreateGroup{ + Admin: "invalid-address", + }, + expErr: true, + }, + "duplicate member addresses not allowed": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Address: myAddr.String(), Weight: "1"}, + {Address: myAddr.String(), Weight: "2"}, + }, + }, + expErr: true, + }, + "negative member's weight not allowed": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Address: myAddr.String(), Weight: "-1"}, + }, + }, + expErr: true, + }, + "empty member's weight not allowed": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{{Address: myAddr.String()}}, + }, + expErr: true, + }, + "zero member's weight not allowed": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{{Address: myAddr.String(), Weight: "0"}}, + }, + expErr: true, + }, + "member address required": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Weight: "1"}, + }, + }, + expErr: true, + }, + "valid member address required": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Address: "invalid-address", Weight: "1"}, + }, + }, + expErr: true, + }, + "group metadata too long": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Metadata: bytes.Repeat([]byte{1}, 256), + }, + expErr: true, + }, + "members metadata too long": { + src: MsgCreateGroup{ + Admin: myAddr.String(), + Members: []Member{ + {Address: myAddr.String(), Weight: "1", Metadata: bytes.Repeat([]byte{1}, 256)}, + }, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgCreateGroupSigner(t *testing.T) { + _, _, myAddr := testdata.KeyTestPubAddr() + assert.Equal(t, []sdk.AccAddress{myAddr}, MsgCreateGroup{Admin: myAddr.String()}.GetSigners()) +} + +func TestMsgCreateGroupAccount(t *testing.T) { + _, _, myAddr := testdata.KeyTestPubAddr() + + specs := map[string]struct { + admin sdk.AccAddress + group uint64 + metadata []byte + threshold string + timeout proto.Duration + expErr bool + }{ + "all good with minimum fields set": { + admin: myAddr, + group: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + }, + "zero threshold not allowed": { + admin: myAddr, + group: 1, + threshold: "0", + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + "admin required": { + group: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + "group required": { + admin: myAddr, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + "decision policy required": { + admin: myAddr, + group: 1, + expErr: true, + }, + "decision policy without timeout": { + admin: myAddr, + group: 1, + threshold: "1", + expErr: true, + }, + "decision policy with invalid timeout": { + admin: myAddr, + group: 1, + threshold: "1", + timeout: proto.Duration{Seconds: -1}, + expErr: true, + }, + "decision policy without threshold": { + admin: myAddr, + group: 1, + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + "decision policy with negative threshold": { + admin: myAddr, + group: 1, + threshold: "-1", + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + "metadata too long": { + admin: myAddr, + group: 1, + metadata: []byte(strings.Repeat("a", 256)), + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + m, err := NewMsgCreateGroupAccount( + spec.admin, + spec.group, + spec.metadata, + &ThresholdDecisionPolicy{ + Threshold: spec.threshold, + Timeout: spec.timeout, + }, + ) + require.NoError(t, err) + + if spec.expErr { + require.Error(t, m.ValidateBasic()) + } else { + require.NoError(t, m.ValidateBasic()) + } + }) + } +} + +func TestMsgCreateProposalRequest(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + groupAccAddr := addr.String() + + _, _, addr = testdata.KeyTestPubAddr() + memberAddr := addr.String() + + specs := map[string]struct { + src MsgCreateProposal + expErr bool + }{ + "all good with minimum fields set": { + src: MsgCreateProposal{ + Address: groupAccAddr, + Proposers: []string{memberAddr}, + }, + }, + "group account required": { + src: MsgCreateProposal{ + Proposers: []string{memberAddr}, + }, + expErr: true, + }, + "proposers required": { + src: MsgCreateProposal{ + Address: groupAccAddr, + }, + expErr: true, + }, + "valid proposer address required": { + src: MsgCreateProposal{ + Address: groupAccAddr, + Proposers: []string{"invalid-member-address"}, + }, + expErr: true, + }, + "no duplicate proposers": { + src: MsgCreateProposal{ + Address: groupAccAddr, + Proposers: []string{memberAddr, memberAddr}, + }, + expErr: true, + }, + "empty proposer address not allowed": { + src: MsgCreateProposal{ + Address: groupAccAddr, + Proposers: []string{memberAddr, ""}, + }, + expErr: true, + }, + "metadata too long": { + src: MsgCreateProposal{ + Address: groupAccAddr, + Proposers: []string{memberAddr}, + Metadata: bytes.Repeat([]byte{1}, 256), + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgVote(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + memberAddr := addr.String() + + specs := map[string]struct { + src MsgVote + expErr bool + }{ + "all good with minimum fields set": { + src: MsgVote{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Voter: memberAddr, + }, + }, + "proposal required": { + src: MsgVote{ + Choice: Choice_CHOICE_YES, + Voter: memberAddr, + }, + expErr: true, + }, + "choice required": { + src: MsgVote{ + ProposalId: 1, + Voter: memberAddr, + }, + expErr: true, + }, + "valid choice required": { + src: MsgVote{ + ProposalId: 1, + Choice: 5, + Voter: memberAddr, + }, + expErr: true, + }, + "voter required": { + src: MsgVote{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + }, + expErr: true, + }, + "valid voter address required": { + src: MsgVote{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Voter: "invalid-member-address", + }, + expErr: true, + }, + "empty voters address not allowed": { + src: MsgVote{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Voter: "", + }, + expErr: true, + }, + "metadata too long": { + src: MsgVote{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Voter: memberAddr, + Metadata: bytes.Repeat([]byte{1}, 256), + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgVoteBasicResponse(t *testing.T) { + sk, pk, addr := testdata.KeyTestPubAddrBls12381() + memberAddr := addr.String() + + sk2, pk2, addr2 := testdata.KeyTestPubAddrBls12381() + + now := time.Now() + expiry, err := gogotypes.TimestampProto(now.Add(time.Second * 3000)) + require.NoError(t, err) + + msg := MsgVoteBasic{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + } + err = msg.ValidateBasic() + require.NoError(t, err) + + bytesToSign := msg.GetSignBytes() + + sig, err := sk.Sign(bytesToSign) + require.NoError(t, err) + + sig2, err := sk2.Sign(bytesToSign) + require.NoError(t, err) + + pubKeyAny, err := codectypes.NewAnyWithValue(pk) + require.NoError(t, err) + + pubKeyAny2, err := codectypes.NewAnyWithValue(pk2) + require.NoError(t, err) + + specs := map[string]struct { + src MsgVoteBasicResponse + expErr bool + sigErr bool + }{ + "all good": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny, + Sig: sig, + }, + }, + "proposal required": { + src: MsgVoteBasicResponse{ + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny, + Sig: sig, + }, + expErr: true, + }, + "choice required": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny, + Sig: sig, + }, + expErr: true, + }, + "valid choice required": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: 5, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny, + Sig: sig, + }, + expErr: true, + }, + "voter required": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + PubKey: pubKeyAny, + Sig: sig, + }, + expErr: true, + }, + "valid voter address required": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: "invalid member address", + PubKey: pubKeyAny, + Sig: sig, + }, + expErr: true, + }, + "wrong voter": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: addr2.String(), + PubKey: pubKeyAny, + Sig: sig, + }, + sigErr: true, + }, + "wrong choice": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_NO, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny, + Sig: sig, + }, + sigErr: true, + }, + "wrong signature": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: addr.String(), + PubKey: pubKeyAny, + Sig: sig2, + }, + sigErr: true, + }, + "empty public key": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: memberAddr, + Sig: sig, + }, + expErr: true, + }, + "wrong public key": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny2, + Sig: sig, + }, + sigErr: true, + }, + "empty voters address not allowed": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + PubKey: pubKeyAny, + Sig: sig, + }, + expErr: true, + }, + "empty signature": { + src: MsgVoteBasicResponse{ + ProposalId: 1, + Choice: Choice_CHOICE_YES, + Expiry: *expiry, + Voter: memberAddr, + PubKey: pubKeyAny, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + err = spec.src.VerifySignature() + if spec.sigErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + } + }) + } +} + +func TestMsgVoteAggRequest(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddrBls12381() + memberAddr := addr.String() + + now := time.Now() + expiry, err := gogotypes.TimestampProto(now.Add(time.Second * 3000)) + require.NoError(t, err) + + specs := map[string]struct { + src MsgVoteAgg + expErr bool + }{ + "all good with minimus fields": { + src: MsgVoteAgg{ + Sender: memberAddr, + ProposalId: 1, + Votes: []Choice{Choice_CHOICE_YES, Choice_CHOICE_NO}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + }, + "proposal required": { + src: MsgVoteAgg{ + Sender: memberAddr, + Votes: []Choice{Choice_CHOICE_YES, Choice_CHOICE_NO}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "votes required": { + src: MsgVoteAgg{ + Sender: memberAddr, + ProposalId: 1, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "valid votes required": { + src: MsgVoteAgg{ + Sender: memberAddr, + ProposalId: 1, + Votes: []Choice{5, Choice_CHOICE_NO}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "sender required": { + src: MsgVoteAgg{ + ProposalId: 1, + Votes: []Choice{Choice_CHOICE_YES, Choice_CHOICE_NO}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "valid sender address required": { + src: MsgVoteAgg{ + Sender: "invalid sender address", + ProposalId: 1, + Votes: []Choice{Choice_CHOICE_YES, Choice_CHOICE_NO}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "empty signature": { + src: MsgVoteAgg{ + Sender: memberAddr, + ProposalId: 1, + Votes: []Choice{Choice_CHOICE_YES, Choice_CHOICE_NO}, + Expiry: *expiry, + }, + expErr: true, + }, + "metadata too long": { + src: MsgVoteAgg{ + Sender: memberAddr, + ProposalId: 1, + Votes: []Choice{Choice_CHOICE_YES, Choice_CHOICE_NO}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + Metadata: bytes.Repeat([]byte{1}, 256), + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgCreatePollRequest(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + memberAddr := addr.String() + + now := time.Now() + expiry, err := gogotypes.TimestampProto(now.Add(time.Second * 3000)) + require.NoError(t, err) + + longTitle := strings.Repeat("my title", 256) + manyOptions := make([]string, 300) + for i, _ := range manyOptions { + manyOptions[i] = fmt.Sprintf("option-%d", i) + } + + specs := map[string]struct { + src MsgCreatePoll + expErr bool + }{ + "all good": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + }, + "group id required": { + src: MsgCreatePoll{ + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "Creator required": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "valid creator address required": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: "invalid member address", + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "title required": { + src: MsgCreatePoll{ + GroupId: 1, + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "options required": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "empty option": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", ""}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "repeated options": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "alice"}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "vote limit required": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + Timeout: *expiry, + }, + expErr: true, + }, + "vote limit exceed": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + VoteLimit: 3, + Timeout: *expiry, + }, + expErr: true, + }, + "metadata too long": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + VoteLimit: 1, + Metadata: bytes.Repeat([]byte{1}, 256), + Timeout: *expiry, + }, + expErr: true, + }, + "title too long": { + src: MsgCreatePoll{ + GroupId: 1, + Title: longTitle, + Options: Options{Titles: []string{"alice", "bob"}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "option title too long": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: []string{"alice", longTitle}}, + Creator: memberAddr, + VoteLimit: 1, + Timeout: *expiry, + }, + expErr: true, + }, + "too many options": { + src: MsgCreatePoll{ + GroupId: 1, + Title: "2022 Election", + Options: Options{Titles: manyOptions}, + Creator: memberAddr, + VoteLimit: 2, + Timeout: *expiry, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgVotePoll(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + memberAddr := addr.String() + + specs := map[string]struct { + src MsgVotePoll + expErr bool + }{ + "all good with minimum fields set": { + src: MsgVotePoll{ + PollId: 1, + Voter: memberAddr, + Options: Options{Titles: []string{"alice"}}, + }, + }, + "poll required": { + src: MsgVotePoll{ + Voter: memberAddr, + Options: Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "options required": { + src: MsgVotePoll{ + PollId: 1, + Voter: memberAddr, + }, + expErr: true, + }, + "valid options required": { + src: MsgVotePoll{ + PollId: 1, + Voter: memberAddr, + Options: Options{Titles: []string{"alice", ""}}, + }, + expErr: true, + }, + "voter required": { + src: MsgVotePoll{ + PollId: 1, + Options: Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "valid voter address required": { + src: MsgVotePoll{ + PollId: 1, + Voter: "invalid member address", + Options: Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "empty voters address not allowed": { + src: MsgVotePoll{ + PollId: 1, + Voter: "", + Options: Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "metadata too long": { + src: MsgVotePoll{ + PollId: 1, + Voter: memberAddr, + Options: Options{Titles: []string{"alice"}}, + Metadata: bytes.Repeat([]byte{1}, 256), + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestMsgVotePollAggRequest(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddrBls12381() + memberAddr := addr.String() + + now := time.Now() + expiry, err := gogotypes.TimestampProto(now.Add(time.Second * 3000)) + require.NoError(t, err) + + specs := map[string]struct { + src MsgVotePollAgg + expErr bool + }{ + "all good with minimus fields": { + src: MsgVotePollAgg{ + Sender: memberAddr, + PollId: 1, + Votes: []Options{Options{Titles: []string{"alice", "bob"}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + }, + "poll required": { + src: MsgVotePollAgg{ + Sender: memberAddr, + Votes: []Options{Options{Titles: []string{"alice", "bob"}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "votes required": { + src: MsgVotePollAgg{ + Sender: memberAddr, + PollId: 1, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "valid votes required": { + src: MsgVotePollAgg{ + Sender: memberAddr, + PollId: 1, + Votes: []Options{Options{Titles: []string{"alice", ""}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "sender required": { + src: MsgVotePollAgg{ + PollId: 1, + Votes: []Options{Options{Titles: []string{"alice", "bob"}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "valid sender address required": { + src: MsgVotePollAgg{ + Sender: "invalid sender address", + PollId: 1, + Votes: []Options{Options{Titles: []string{"alice", "bob"}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + }, + expErr: true, + }, + "empty signature": { + src: MsgVotePollAgg{ + Sender: memberAddr, + PollId: 1, + Votes: []Options{Options{Titles: []string{"alice", "bob"}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + }, + expErr: true, + }, + "metadata too long": { + src: MsgVotePollAgg{ + Sender: memberAddr, + PollId: 1, + Votes: []Options{Options{Titles: []string{"alice", "bob"}}, Options{Titles: []string{"alice"}}}, + Expiry: *expiry, + AggSig: []byte("does not check signature"), + Metadata: bytes.Repeat([]byte{1}, 256), + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/group/proposal.go b/x/group/proposal.go new file mode 100644 index 0000000000..b9ff15aea1 --- /dev/null +++ b/x/group/proposal.go @@ -0,0 +1,97 @@ +package group + +import ( + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/regen/types/module/server" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +func (p *Proposal) GetMsgs() []sdk.Msg { + msgs, err := server.GetMsgs(p.Msgs) + if err != nil { + panic(err) + } + return msgs +} + +func (p *Proposal) SetMsgs(msgs []sdk.Msg) error { + anys, err := server.SetMsgs(msgs) + if err != nil { + return err + } + p.Msgs = anys + return nil +} + +func (p Proposal) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(p.Address) + if err != nil { + return sdkerrors.Wrap(err, "group account") + } + + if len(p.Proposers) == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposers") + } + addrs := make([]sdk.AccAddress, len(p.Proposers)) + for i, proposer := range p.Proposers { + addr, err := sdk.AccAddressFromBech32(proposer) + if err != nil { + return sdkerrors.Wrap(err, "proposers") + } + addrs[i] = addr + } + if err := AccAddresses(addrs).ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "proposers") + } + + if p.SubmittedAt.Seconds == 0 && p.SubmittedAt.Nanos == 0 { + return sdkerrors.Wrap(ErrEmpty, "submitted at") + } + if p.GroupVersion == 0 { + return sdkerrors.Wrap(ErrEmpty, "group version") + } + if p.GroupAccountVersion == 0 { + return sdkerrors.Wrap(ErrEmpty, "group account version") + } + if p.Status == ProposalStatusInvalid { + return sdkerrors.Wrap(ErrEmpty, "status") + } + if _, ok := Proposal_Status_name[int32(p.Status)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "status") + } + if p.Result == ProposalResultInvalid { + return sdkerrors.Wrap(ErrEmpty, "result") + } + if _, ok := Proposal_Result_name[int32(p.Result)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "result") + } + if p.ExecutorResult == ProposalExecutorResultInvalid { + return sdkerrors.Wrap(ErrEmpty, "executor result") + } + if _, ok := Proposal_ExecutorResult_name[int32(p.ExecutorResult)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "executor result") + } + if err := p.VoteState.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "vote state") + } + if p.Timeout.Seconds == 0 && p.Timeout.Nanos == 0 { + return sdkerrors.Wrap(ErrEmpty, "timeout") + } + msgs := p.GetMsgs() + for i, msg := range msgs { + if err := msg.ValidateBasic(); err != nil { + return sdkerrors.Wrapf(err, "message %d", i) + } + } + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (p Proposal) UnpackInterfaces(unpacker types.AnyUnpacker) error { + return server.UnpackInterfaces(unpacker, p.Msgs) +} + +func (p Proposal) PrimaryKeyFields() []interface{} { + return []interface{}{p.ProposalId} +} diff --git a/x/group/query.pb.go b/x/group/query.pb.go new file mode 100644 index 0000000000..e74a3a1306 --- /dev/null +++ b/x/group/query.pb.go @@ -0,0 +1,8231 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: regen/group/v1alpha1/query.proto + +package group + +import ( + context "context" + fmt "fmt" + query "github.com/cosmos/cosmos-sdk/types/query" + _ "github.com/gogo/protobuf/gogoproto" + grpc1 "github.com/gogo/protobuf/grpc" + proto "github.com/gogo/protobuf/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + 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" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// QueryGroupInfoRequest is the Query/GroupInfo request type. +type QueryGroupInfoRequest struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` +} + +func (m *QueryGroupInfoRequest) Reset() { *m = QueryGroupInfoRequest{} } +func (m *QueryGroupInfoRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupInfoRequest) ProtoMessage() {} +func (*QueryGroupInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{0} +} +func (m *QueryGroupInfoRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupInfoRequest.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 *QueryGroupInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupInfoRequest.Merge(m, src) +} +func (m *QueryGroupInfoRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupInfoRequest proto.InternalMessageInfo + +func (m *QueryGroupInfoRequest) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +// QueryGroupInfoResponse is the Query/GroupInfo response type. +type QueryGroupInfoResponse struct { + // info is the GroupInfo for the group. + Info *GroupInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` +} + +func (m *QueryGroupInfoResponse) Reset() { *m = QueryGroupInfoResponse{} } +func (m *QueryGroupInfoResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupInfoResponse) ProtoMessage() {} +func (*QueryGroupInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{1} +} +func (m *QueryGroupInfoResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupInfoResponse.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 *QueryGroupInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupInfoResponse.Merge(m, src) +} +func (m *QueryGroupInfoResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupInfoResponse proto.InternalMessageInfo + +func (m *QueryGroupInfoResponse) GetInfo() *GroupInfo { + if m != nil { + return m.Info + } + return nil +} + +// QueryGroupAccountInfoRequest is the Query/GroupAccountInfo request type. +type QueryGroupAccountInfoRequest struct { + // address is the account address of the group account. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *QueryGroupAccountInfoRequest) Reset() { *m = QueryGroupAccountInfoRequest{} } +func (m *QueryGroupAccountInfoRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupAccountInfoRequest) ProtoMessage() {} +func (*QueryGroupAccountInfoRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{2} +} +func (m *QueryGroupAccountInfoRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupAccountInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupAccountInfoRequest.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 *QueryGroupAccountInfoRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupAccountInfoRequest.Merge(m, src) +} +func (m *QueryGroupAccountInfoRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupAccountInfoRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupAccountInfoRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupAccountInfoRequest proto.InternalMessageInfo + +func (m *QueryGroupAccountInfoRequest) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +// QueryGroupAccountInfoResponse is the Query/GroupAccountInfo response type. +type QueryGroupAccountInfoResponse struct { + // info is the GroupAccountInfo for the group account. + Info *GroupAccountInfo `protobuf:"bytes,1,opt,name=info,proto3" json:"info,omitempty"` +} + +func (m *QueryGroupAccountInfoResponse) Reset() { *m = QueryGroupAccountInfoResponse{} } +func (m *QueryGroupAccountInfoResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupAccountInfoResponse) ProtoMessage() {} +func (*QueryGroupAccountInfoResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{3} +} +func (m *QueryGroupAccountInfoResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupAccountInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupAccountInfoResponse.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 *QueryGroupAccountInfoResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupAccountInfoResponse.Merge(m, src) +} +func (m *QueryGroupAccountInfoResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupAccountInfoResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupAccountInfoResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupAccountInfoResponse proto.InternalMessageInfo + +func (m *QueryGroupAccountInfoResponse) GetInfo() *GroupAccountInfo { + if m != nil { + return m.Info + } + return nil +} + +// QueryGroupMembersRequest is the Query/GroupMembersRequest request type. +type QueryGroupMembersRequest struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupMembersRequest) Reset() { *m = QueryGroupMembersRequest{} } +func (m *QueryGroupMembersRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupMembersRequest) ProtoMessage() {} +func (*QueryGroupMembersRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{4} +} +func (m *QueryGroupMembersRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupMembersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupMembersRequest.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 *QueryGroupMembersRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupMembersRequest.Merge(m, src) +} +func (m *QueryGroupMembersRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupMembersRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupMembersRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupMembersRequest proto.InternalMessageInfo + +func (m *QueryGroupMembersRequest) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *QueryGroupMembersRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupMembersResponse is the Query/GroupMembersResponse response type. +type QueryGroupMembersResponse struct { + // members are the members of the group with given group_id. + Members []*GroupMember `protobuf:"bytes,1,rep,name=members,proto3" json:"members,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupMembersResponse) Reset() { *m = QueryGroupMembersResponse{} } +func (m *QueryGroupMembersResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupMembersResponse) ProtoMessage() {} +func (*QueryGroupMembersResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{5} +} +func (m *QueryGroupMembersResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupMembersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupMembersResponse.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 *QueryGroupMembersResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupMembersResponse.Merge(m, src) +} +func (m *QueryGroupMembersResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupMembersResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupMembersResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupMembersResponse proto.InternalMessageInfo + +func (m *QueryGroupMembersResponse) GetMembers() []*GroupMember { + if m != nil { + return m.Members + } + return nil +} + +func (m *QueryGroupMembersResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupsByAdminRequest is the Query/GroupsByAdminRequest request type. +type QueryGroupsByAdminRequest struct { + // admin is the account address of a group's admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupsByAdminRequest) Reset() { *m = QueryGroupsByAdminRequest{} } +func (m *QueryGroupsByAdminRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupsByAdminRequest) ProtoMessage() {} +func (*QueryGroupsByAdminRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{6} +} +func (m *QueryGroupsByAdminRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupsByAdminRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupsByAdminRequest.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 *QueryGroupsByAdminRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupsByAdminRequest.Merge(m, src) +} +func (m *QueryGroupsByAdminRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupsByAdminRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupsByAdminRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupsByAdminRequest proto.InternalMessageInfo + +func (m *QueryGroupsByAdminRequest) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *QueryGroupsByAdminRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupsByAdminResponse is the Query/GroupsByAdminResponse response type. +type QueryGroupsByAdminResponse struct { + // groups are the groups info with the provided admin. + Groups []*GroupInfo `protobuf:"bytes,1,rep,name=groups,proto3" json:"groups,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupsByAdminResponse) Reset() { *m = QueryGroupsByAdminResponse{} } +func (m *QueryGroupsByAdminResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupsByAdminResponse) ProtoMessage() {} +func (*QueryGroupsByAdminResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{7} +} +func (m *QueryGroupsByAdminResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupsByAdminResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupsByAdminResponse.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 *QueryGroupsByAdminResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupsByAdminResponse.Merge(m, src) +} +func (m *QueryGroupsByAdminResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupsByAdminResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupsByAdminResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupsByAdminResponse proto.InternalMessageInfo + +func (m *QueryGroupsByAdminResponse) GetGroups() []*GroupInfo { + if m != nil { + return m.Groups + } + return nil +} + +func (m *QueryGroupsByAdminResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupAccountsByGroupRequest is the Query/GroupAccountsByGroup request type. +type QueryGroupAccountsByGroupRequest struct { + // group_id is the unique ID of the group account's group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupAccountsByGroupRequest) Reset() { *m = QueryGroupAccountsByGroupRequest{} } +func (m *QueryGroupAccountsByGroupRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupAccountsByGroupRequest) ProtoMessage() {} +func (*QueryGroupAccountsByGroupRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{8} +} +func (m *QueryGroupAccountsByGroupRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupAccountsByGroupRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupAccountsByGroupRequest.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 *QueryGroupAccountsByGroupRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupAccountsByGroupRequest.Merge(m, src) +} +func (m *QueryGroupAccountsByGroupRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupAccountsByGroupRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupAccountsByGroupRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupAccountsByGroupRequest proto.InternalMessageInfo + +func (m *QueryGroupAccountsByGroupRequest) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *QueryGroupAccountsByGroupRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupAccountsByGroupResponse is the Query/GroupAccountsByGroup response type. +type QueryGroupAccountsByGroupResponse struct { + // group_accounts are the group accounts info associated with the provided group. + GroupAccounts []*GroupAccountInfo `protobuf:"bytes,1,rep,name=group_accounts,json=groupAccounts,proto3" json:"group_accounts,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupAccountsByGroupResponse) Reset() { *m = QueryGroupAccountsByGroupResponse{} } +func (m *QueryGroupAccountsByGroupResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupAccountsByGroupResponse) ProtoMessage() {} +func (*QueryGroupAccountsByGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{9} +} +func (m *QueryGroupAccountsByGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupAccountsByGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupAccountsByGroupResponse.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 *QueryGroupAccountsByGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupAccountsByGroupResponse.Merge(m, src) +} +func (m *QueryGroupAccountsByGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupAccountsByGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupAccountsByGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupAccountsByGroupResponse proto.InternalMessageInfo + +func (m *QueryGroupAccountsByGroupResponse) GetGroupAccounts() []*GroupAccountInfo { + if m != nil { + return m.GroupAccounts + } + return nil +} + +func (m *QueryGroupAccountsByGroupResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupAccountsByAdminRequest is the Query/GroupAccountsByAdmin request type. +type QueryGroupAccountsByAdminRequest struct { + // admin is the admin address of the group account. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupAccountsByAdminRequest) Reset() { *m = QueryGroupAccountsByAdminRequest{} } +func (m *QueryGroupAccountsByAdminRequest) String() string { return proto.CompactTextString(m) } +func (*QueryGroupAccountsByAdminRequest) ProtoMessage() {} +func (*QueryGroupAccountsByAdminRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{10} +} +func (m *QueryGroupAccountsByAdminRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupAccountsByAdminRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupAccountsByAdminRequest.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 *QueryGroupAccountsByAdminRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupAccountsByAdminRequest.Merge(m, src) +} +func (m *QueryGroupAccountsByAdminRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupAccountsByAdminRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupAccountsByAdminRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupAccountsByAdminRequest proto.InternalMessageInfo + +func (m *QueryGroupAccountsByAdminRequest) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *QueryGroupAccountsByAdminRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryGroupAccountsByAdminResponse is the Query/GroupAccountsByAdmin response type. +type QueryGroupAccountsByAdminResponse struct { + // group_accounts are the group accounts info with provided admin. + GroupAccounts []*GroupAccountInfo `protobuf:"bytes,1,rep,name=group_accounts,json=groupAccounts,proto3" json:"group_accounts,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryGroupAccountsByAdminResponse) Reset() { *m = QueryGroupAccountsByAdminResponse{} } +func (m *QueryGroupAccountsByAdminResponse) String() string { return proto.CompactTextString(m) } +func (*QueryGroupAccountsByAdminResponse) ProtoMessage() {} +func (*QueryGroupAccountsByAdminResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{11} +} +func (m *QueryGroupAccountsByAdminResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryGroupAccountsByAdminResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryGroupAccountsByAdminResponse.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 *QueryGroupAccountsByAdminResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryGroupAccountsByAdminResponse.Merge(m, src) +} +func (m *QueryGroupAccountsByAdminResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryGroupAccountsByAdminResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryGroupAccountsByAdminResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryGroupAccountsByAdminResponse proto.InternalMessageInfo + +func (m *QueryGroupAccountsByAdminResponse) GetGroupAccounts() []*GroupAccountInfo { + if m != nil { + return m.GroupAccounts + } + return nil +} + +func (m *QueryGroupAccountsByAdminResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryProposalRequest is the Query/Proposal request type. +type QueryProposalRequest struct { + // proposal_id is the unique ID of a proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *QueryProposalRequest) Reset() { *m = QueryProposalRequest{} } +func (m *QueryProposalRequest) String() string { return proto.CompactTextString(m) } +func (*QueryProposalRequest) ProtoMessage() {} +func (*QueryProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{12} +} +func (m *QueryProposalRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalRequest.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 *QueryProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalRequest.Merge(m, src) +} +func (m *QueryProposalRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalRequest proto.InternalMessageInfo + +func (m *QueryProposalRequest) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +// QueryProposalResponse is the Query/Proposal response type. +type QueryProposalResponse struct { + // proposal is the proposal info. + Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` +} + +func (m *QueryProposalResponse) Reset() { *m = QueryProposalResponse{} } +func (m *QueryProposalResponse) String() string { return proto.CompactTextString(m) } +func (*QueryProposalResponse) ProtoMessage() {} +func (*QueryProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{13} +} +func (m *QueryProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalResponse.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 *QueryProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalResponse.Merge(m, src) +} +func (m *QueryProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalResponse proto.InternalMessageInfo + +func (m *QueryProposalResponse) GetProposal() *Proposal { + if m != nil { + return m.Proposal + } + return nil +} + +// QueryProposalsByGroupAccountRequest is the Query/ProposalByGroupAccount request type. +type QueryProposalsByGroupAccountRequest struct { + // address is the group account address related to proposals. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryProposalsByGroupAccountRequest) Reset() { *m = QueryProposalsByGroupAccountRequest{} } +func (m *QueryProposalsByGroupAccountRequest) String() string { return proto.CompactTextString(m) } +func (*QueryProposalsByGroupAccountRequest) ProtoMessage() {} +func (*QueryProposalsByGroupAccountRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{14} +} +func (m *QueryProposalsByGroupAccountRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalsByGroupAccountRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalsByGroupAccountRequest.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 *QueryProposalsByGroupAccountRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalsByGroupAccountRequest.Merge(m, src) +} +func (m *QueryProposalsByGroupAccountRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalsByGroupAccountRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalsByGroupAccountRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalsByGroupAccountRequest proto.InternalMessageInfo + +func (m *QueryProposalsByGroupAccountRequest) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *QueryProposalsByGroupAccountRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryProposalsByGroupAccountResponse is the Query/ProposalByGroupAccount response type. +type QueryProposalsByGroupAccountResponse struct { + // proposals are the proposals with given group account. + Proposals []*Proposal `protobuf:"bytes,1,rep,name=proposals,proto3" json:"proposals,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryProposalsByGroupAccountResponse) Reset() { *m = QueryProposalsByGroupAccountResponse{} } +func (m *QueryProposalsByGroupAccountResponse) String() string { return proto.CompactTextString(m) } +func (*QueryProposalsByGroupAccountResponse) ProtoMessage() {} +func (*QueryProposalsByGroupAccountResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{15} +} +func (m *QueryProposalsByGroupAccountResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryProposalsByGroupAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryProposalsByGroupAccountResponse.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 *QueryProposalsByGroupAccountResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryProposalsByGroupAccountResponse.Merge(m, src) +} +func (m *QueryProposalsByGroupAccountResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryProposalsByGroupAccountResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryProposalsByGroupAccountResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryProposalsByGroupAccountResponse proto.InternalMessageInfo + +func (m *QueryProposalsByGroupAccountResponse) GetProposals() []*Proposal { + if m != nil { + return m.Proposals + } + return nil +} + +func (m *QueryProposalsByGroupAccountResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVoteByProposalVoterResponse is the Query/VoteByProposalVoter request type. +type QueryVoteByProposalVoterRequest struct { + // proposal_id is the unique ID of a proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // voter is a proposal voter account address. + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` +} + +func (m *QueryVoteByProposalVoterRequest) Reset() { *m = QueryVoteByProposalVoterRequest{} } +func (m *QueryVoteByProposalVoterRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVoteByProposalVoterRequest) ProtoMessage() {} +func (*QueryVoteByProposalVoterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{16} +} +func (m *QueryVoteByProposalVoterRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteByProposalVoterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteByProposalVoterRequest.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 *QueryVoteByProposalVoterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteByProposalVoterRequest.Merge(m, src) +} +func (m *QueryVoteByProposalVoterRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteByProposalVoterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteByProposalVoterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteByProposalVoterRequest proto.InternalMessageInfo + +func (m *QueryVoteByProposalVoterRequest) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *QueryVoteByProposalVoterRequest) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +// QueryVoteByProposalVoterResponse is the Query/VoteByProposalVoter response type. +type QueryVoteByProposalVoterResponse struct { + // vote is the vote with given proposal_id and voter. + Vote *Vote `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` +} + +func (m *QueryVoteByProposalVoterResponse) Reset() { *m = QueryVoteByProposalVoterResponse{} } +func (m *QueryVoteByProposalVoterResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVoteByProposalVoterResponse) ProtoMessage() {} +func (*QueryVoteByProposalVoterResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{17} +} +func (m *QueryVoteByProposalVoterResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteByProposalVoterResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteByProposalVoterResponse.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 *QueryVoteByProposalVoterResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteByProposalVoterResponse.Merge(m, src) +} +func (m *QueryVoteByProposalVoterResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteByProposalVoterResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteByProposalVoterResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteByProposalVoterResponse proto.InternalMessageInfo + +func (m *QueryVoteByProposalVoterResponse) GetVote() *Vote { + if m != nil { + return m.Vote + } + return nil +} + +// QueryVotesByProposalResponse is the Query/VotesByProposal request type. +type QueryVotesByProposalRequest struct { + // proposal_id is the unique ID of a proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesByProposalRequest) Reset() { *m = QueryVotesByProposalRequest{} } +func (m *QueryVotesByProposalRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVotesByProposalRequest) ProtoMessage() {} +func (*QueryVotesByProposalRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{18} +} +func (m *QueryVotesByProposalRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesByProposalRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesByProposalRequest.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 *QueryVotesByProposalRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesByProposalRequest.Merge(m, src) +} +func (m *QueryVotesByProposalRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesByProposalRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesByProposalRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesByProposalRequest proto.InternalMessageInfo + +func (m *QueryVotesByProposalRequest) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *QueryVotesByProposalRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVotesByProposalResponse is the Query/VotesByProposal response type. +type QueryVotesByProposalResponse struct { + // votes are the list of votes for given proposal_id. + Votes []*Vote `protobuf:"bytes,1,rep,name=votes,proto3" json:"votes,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesByProposalResponse) Reset() { *m = QueryVotesByProposalResponse{} } +func (m *QueryVotesByProposalResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVotesByProposalResponse) ProtoMessage() {} +func (*QueryVotesByProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{19} +} +func (m *QueryVotesByProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesByProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesByProposalResponse.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 *QueryVotesByProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesByProposalResponse.Merge(m, src) +} +func (m *QueryVotesByProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesByProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesByProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesByProposalResponse proto.InternalMessageInfo + +func (m *QueryVotesByProposalResponse) GetVotes() []*Vote { + if m != nil { + return m.Votes + } + return nil +} + +func (m *QueryVotesByProposalResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVotesByVoterResponse is the Query/VotesByVoter request type. +type QueryVotesByVoterRequest struct { + // voter is a proposal voter account address. + Voter string `protobuf:"bytes,1,opt,name=voter,proto3" json:"voter,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesByVoterRequest) Reset() { *m = QueryVotesByVoterRequest{} } +func (m *QueryVotesByVoterRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVotesByVoterRequest) ProtoMessage() {} +func (*QueryVotesByVoterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{20} +} +func (m *QueryVotesByVoterRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesByVoterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesByVoterRequest.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 *QueryVotesByVoterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesByVoterRequest.Merge(m, src) +} +func (m *QueryVotesByVoterRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesByVoterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesByVoterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesByVoterRequest proto.InternalMessageInfo + +func (m *QueryVotesByVoterRequest) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *QueryVotesByVoterRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVotesByVoterResponse is the Query/VotesByVoter response type. +type QueryVotesByVoterResponse struct { + // votes are the list of votes by given voter. + Votes []*Vote `protobuf:"bytes,1,rep,name=votes,proto3" json:"votes,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesByVoterResponse) Reset() { *m = QueryVotesByVoterResponse{} } +func (m *QueryVotesByVoterResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVotesByVoterResponse) ProtoMessage() {} +func (*QueryVotesByVoterResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{21} +} +func (m *QueryVotesByVoterResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesByVoterResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesByVoterResponse.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 *QueryVotesByVoterResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesByVoterResponse.Merge(m, src) +} +func (m *QueryVotesByVoterResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesByVoterResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesByVoterResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesByVoterResponse proto.InternalMessageInfo + +func (m *QueryVotesByVoterResponse) GetVotes() []*Vote { + if m != nil { + return m.Votes + } + return nil +} + +func (m *QueryVotesByVoterResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryPollRequest is the Query/Poll request type. +type QueryPollRequest struct { + // poll_id is the unique ID of a poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` +} + +func (m *QueryPollRequest) Reset() { *m = QueryPollRequest{} } +func (m *QueryPollRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPollRequest) ProtoMessage() {} +func (*QueryPollRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{22} +} +func (m *QueryPollRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPollRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPollRequest.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 *QueryPollRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPollRequest.Merge(m, src) +} +func (m *QueryPollRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPollRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPollRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPollRequest proto.InternalMessageInfo + +func (m *QueryPollRequest) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +// QueryPollResponse is the Query/Poll response type. +type QueryPollResponse struct { + // poll is the poll info. + Poll *Poll `protobuf:"bytes,1,opt,name=poll,proto3" json:"poll,omitempty"` +} + +func (m *QueryPollResponse) Reset() { *m = QueryPollResponse{} } +func (m *QueryPollResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPollResponse) ProtoMessage() {} +func (*QueryPollResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{23} +} +func (m *QueryPollResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPollResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPollResponse.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 *QueryPollResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPollResponse.Merge(m, src) +} +func (m *QueryPollResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPollResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPollResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPollResponse proto.InternalMessageInfo + +func (m *QueryPollResponse) GetPoll() *Poll { + if m != nil { + return m.Poll + } + return nil +} + +// QueryPollsByGroupRequest is the Query/PollByGroup request type. +type QueryPollsByGroupRequest struct { + // group_id is the group id related to polls. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryPollsByGroupRequest) Reset() { *m = QueryPollsByGroupRequest{} } +func (m *QueryPollsByGroupRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPollsByGroupRequest) ProtoMessage() {} +func (*QueryPollsByGroupRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{24} +} +func (m *QueryPollsByGroupRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPollsByGroupRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPollsByGroupRequest.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 *QueryPollsByGroupRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPollsByGroupRequest.Merge(m, src) +} +func (m *QueryPollsByGroupRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPollsByGroupRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPollsByGroupRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPollsByGroupRequest proto.InternalMessageInfo + +func (m *QueryPollsByGroupRequest) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *QueryPollsByGroupRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryPollsByGroupResponse is the Query/PollByGroup response type. +type QueryPollsByGroupResponse struct { + // polls are the polls with given group id. + Polls []*Poll `protobuf:"bytes,1,rep,name=polls,proto3" json:"polls,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryPollsByGroupResponse) Reset() { *m = QueryPollsByGroupResponse{} } +func (m *QueryPollsByGroupResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPollsByGroupResponse) ProtoMessage() {} +func (*QueryPollsByGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{25} +} +func (m *QueryPollsByGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPollsByGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPollsByGroupResponse.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 *QueryPollsByGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPollsByGroupResponse.Merge(m, src) +} +func (m *QueryPollsByGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPollsByGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPollsByGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPollsByGroupResponse proto.InternalMessageInfo + +func (m *QueryPollsByGroupResponse) GetPolls() []*Poll { + if m != nil { + return m.Polls + } + return nil +} + +func (m *QueryPollsByGroupResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryPollsByCreatorRequest is the Query/PollByCreator request type. +type QueryPollsByCreatorRequest struct { + // creator is the creator address related to polls. + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryPollsByCreatorRequest) Reset() { *m = QueryPollsByCreatorRequest{} } +func (m *QueryPollsByCreatorRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPollsByCreatorRequest) ProtoMessage() {} +func (*QueryPollsByCreatorRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{26} +} +func (m *QueryPollsByCreatorRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPollsByCreatorRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPollsByCreatorRequest.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 *QueryPollsByCreatorRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPollsByCreatorRequest.Merge(m, src) +} +func (m *QueryPollsByCreatorRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPollsByCreatorRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPollsByCreatorRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPollsByCreatorRequest proto.InternalMessageInfo + +func (m *QueryPollsByCreatorRequest) GetCreator() string { + if m != nil { + return m.Creator + } + return "" +} + +func (m *QueryPollsByCreatorRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryPollsByCreatorResponse is the Query/PollsByCreator response type. +type QueryPollsByCreatorResponse struct { + // polls are the polls with given creator. + Polls []*Poll `protobuf:"bytes,1,rep,name=polls,proto3" json:"polls,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryPollsByCreatorResponse) Reset() { *m = QueryPollsByCreatorResponse{} } +func (m *QueryPollsByCreatorResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPollsByCreatorResponse) ProtoMessage() {} +func (*QueryPollsByCreatorResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{27} +} +func (m *QueryPollsByCreatorResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPollsByCreatorResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPollsByCreatorResponse.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 *QueryPollsByCreatorResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPollsByCreatorResponse.Merge(m, src) +} +func (m *QueryPollsByCreatorResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPollsByCreatorResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPollsByCreatorResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPollsByCreatorResponse proto.InternalMessageInfo + +func (m *QueryPollsByCreatorResponse) GetPolls() []*Poll { + if m != nil { + return m.Polls + } + return nil +} + +func (m *QueryPollsByCreatorResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVoteForPollByPollVoterRequest is the Query/VotePollByPollVoter request type. +type QueryVoteForPollByPollVoterRequest struct { + // poll_id is the unique ID of a poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // voter is a poll voter account address. + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` +} + +func (m *QueryVoteForPollByPollVoterRequest) Reset() { *m = QueryVoteForPollByPollVoterRequest{} } +func (m *QueryVoteForPollByPollVoterRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVoteForPollByPollVoterRequest) ProtoMessage() {} +func (*QueryVoteForPollByPollVoterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{28} +} +func (m *QueryVoteForPollByPollVoterRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteForPollByPollVoterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteForPollByPollVoterRequest.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 *QueryVoteForPollByPollVoterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteForPollByPollVoterRequest.Merge(m, src) +} +func (m *QueryVoteForPollByPollVoterRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteForPollByPollVoterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteForPollByPollVoterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteForPollByPollVoterRequest proto.InternalMessageInfo + +func (m *QueryVoteForPollByPollVoterRequest) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *QueryVoteForPollByPollVoterRequest) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +// QueryVotesForPollByPollVoterResponse is the Query/VotePollByPollVoter response type. +type QueryVoteForPollByPollVoterResponse struct { + // vote is the vote with given poll_id and voter. + Vote *VotePoll `protobuf:"bytes,1,opt,name=vote,proto3" json:"vote,omitempty"` +} + +func (m *QueryVoteForPollByPollVoterResponse) Reset() { *m = QueryVoteForPollByPollVoterResponse{} } +func (m *QueryVoteForPollByPollVoterResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVoteForPollByPollVoterResponse) ProtoMessage() {} +func (*QueryVoteForPollByPollVoterResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{29} +} +func (m *QueryVoteForPollByPollVoterResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVoteForPollByPollVoterResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVoteForPollByPollVoterResponse.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 *QueryVoteForPollByPollVoterResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVoteForPollByPollVoterResponse.Merge(m, src) +} +func (m *QueryVoteForPollByPollVoterResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVoteForPollByPollVoterResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVoteForPollByPollVoterResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVoteForPollByPollVoterResponse proto.InternalMessageInfo + +func (m *QueryVoteForPollByPollVoterResponse) GetVote() *VotePoll { + if m != nil { + return m.Vote + } + return nil +} + +// QueryVotesForPollByPollRequest is the Query/VotePollsByPoll request type. +type QueryVotesForPollByPollRequest struct { + // poll_id is the unique ID of a poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesForPollByPollRequest) Reset() { *m = QueryVotesForPollByPollRequest{} } +func (m *QueryVotesForPollByPollRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVotesForPollByPollRequest) ProtoMessage() {} +func (*QueryVotesForPollByPollRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{30} +} +func (m *QueryVotesForPollByPollRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesForPollByPollRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesForPollByPollRequest.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 *QueryVotesForPollByPollRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesForPollByPollRequest.Merge(m, src) +} +func (m *QueryVotesForPollByPollRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesForPollByPollRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesForPollByPollRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesForPollByPollRequest proto.InternalMessageInfo + +func (m *QueryVotesForPollByPollRequest) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *QueryVotesForPollByPollRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVotesForPollByPollResponse is the Query/VotePollsByPoll response type. +type QueryVotesForPollByPollResponse struct { + // votes are the list of votes for given poll_id. + Votes []*VotePoll `protobuf:"bytes,1,rep,name=votes,proto3" json:"votes,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesForPollByPollResponse) Reset() { *m = QueryVotesForPollByPollResponse{} } +func (m *QueryVotesForPollByPollResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVotesForPollByPollResponse) ProtoMessage() {} +func (*QueryVotesForPollByPollResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{31} +} +func (m *QueryVotesForPollByPollResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesForPollByPollResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesForPollByPollResponse.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 *QueryVotesForPollByPollResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesForPollByPollResponse.Merge(m, src) +} +func (m *QueryVotesForPollByPollResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesForPollByPollResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesForPollByPollResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesForPollByPollResponse proto.InternalMessageInfo + +func (m *QueryVotesForPollByPollResponse) GetVotes() []*VotePoll { + if m != nil { + return m.Votes + } + return nil +} + +func (m *QueryVotesForPollByPollResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVotesForPollByVoterRequest is the Query/VotePollsByVoter request type. +type QueryVotesForPollByVoterRequest struct { + // voter is a poll voter account address. + Voter string `protobuf:"bytes,1,opt,name=voter,proto3" json:"voter,omitempty"` + // pagination defines an optional pagination for the request. + Pagination *query.PageRequest `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesForPollByVoterRequest) Reset() { *m = QueryVotesForPollByVoterRequest{} } +func (m *QueryVotesForPollByVoterRequest) String() string { return proto.CompactTextString(m) } +func (*QueryVotesForPollByVoterRequest) ProtoMessage() {} +func (*QueryVotesForPollByVoterRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{32} +} +func (m *QueryVotesForPollByVoterRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesForPollByVoterRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesForPollByVoterRequest.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 *QueryVotesForPollByVoterRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesForPollByVoterRequest.Merge(m, src) +} +func (m *QueryVotesForPollByVoterRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesForPollByVoterRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesForPollByVoterRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesForPollByVoterRequest proto.InternalMessageInfo + +func (m *QueryVotesForPollByVoterRequest) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *QueryVotesForPollByVoterRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +// QueryVotesForPollByVoterResponse is the Query/VotePollsByVoter response type. +type QueryVotesForPollByVoterResponse struct { + // votes are the list of votes for poll by given voter. + Votes []*VotePoll `protobuf:"bytes,1,rep,name=votes,proto3" json:"votes,omitempty"` + // pagination defines the pagination in the response. + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryVotesForPollByVoterResponse) Reset() { *m = QueryVotesForPollByVoterResponse{} } +func (m *QueryVotesForPollByVoterResponse) String() string { return proto.CompactTextString(m) } +func (*QueryVotesForPollByVoterResponse) ProtoMessage() {} +func (*QueryVotesForPollByVoterResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_2523b81f3b315123, []int{33} +} +func (m *QueryVotesForPollByVoterResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryVotesForPollByVoterResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryVotesForPollByVoterResponse.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 *QueryVotesForPollByVoterResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryVotesForPollByVoterResponse.Merge(m, src) +} +func (m *QueryVotesForPollByVoterResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryVotesForPollByVoterResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryVotesForPollByVoterResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryVotesForPollByVoterResponse proto.InternalMessageInfo + +func (m *QueryVotesForPollByVoterResponse) GetVotes() []*VotePoll { + if m != nil { + return m.Votes + } + return nil +} + +func (m *QueryVotesForPollByVoterResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + +func init() { + proto.RegisterType((*QueryGroupInfoRequest)(nil), "regen.group.v1alpha1.QueryGroupInfoRequest") + proto.RegisterType((*QueryGroupInfoResponse)(nil), "regen.group.v1alpha1.QueryGroupInfoResponse") + proto.RegisterType((*QueryGroupAccountInfoRequest)(nil), "regen.group.v1alpha1.QueryGroupAccountInfoRequest") + proto.RegisterType((*QueryGroupAccountInfoResponse)(nil), "regen.group.v1alpha1.QueryGroupAccountInfoResponse") + proto.RegisterType((*QueryGroupMembersRequest)(nil), "regen.group.v1alpha1.QueryGroupMembersRequest") + proto.RegisterType((*QueryGroupMembersResponse)(nil), "regen.group.v1alpha1.QueryGroupMembersResponse") + proto.RegisterType((*QueryGroupsByAdminRequest)(nil), "regen.group.v1alpha1.QueryGroupsByAdminRequest") + proto.RegisterType((*QueryGroupsByAdminResponse)(nil), "regen.group.v1alpha1.QueryGroupsByAdminResponse") + proto.RegisterType((*QueryGroupAccountsByGroupRequest)(nil), "regen.group.v1alpha1.QueryGroupAccountsByGroupRequest") + proto.RegisterType((*QueryGroupAccountsByGroupResponse)(nil), "regen.group.v1alpha1.QueryGroupAccountsByGroupResponse") + proto.RegisterType((*QueryGroupAccountsByAdminRequest)(nil), "regen.group.v1alpha1.QueryGroupAccountsByAdminRequest") + proto.RegisterType((*QueryGroupAccountsByAdminResponse)(nil), "regen.group.v1alpha1.QueryGroupAccountsByAdminResponse") + proto.RegisterType((*QueryProposalRequest)(nil), "regen.group.v1alpha1.QueryProposalRequest") + proto.RegisterType((*QueryProposalResponse)(nil), "regen.group.v1alpha1.QueryProposalResponse") + proto.RegisterType((*QueryProposalsByGroupAccountRequest)(nil), "regen.group.v1alpha1.QueryProposalsByGroupAccountRequest") + proto.RegisterType((*QueryProposalsByGroupAccountResponse)(nil), "regen.group.v1alpha1.QueryProposalsByGroupAccountResponse") + proto.RegisterType((*QueryVoteByProposalVoterRequest)(nil), "regen.group.v1alpha1.QueryVoteByProposalVoterRequest") + proto.RegisterType((*QueryVoteByProposalVoterResponse)(nil), "regen.group.v1alpha1.QueryVoteByProposalVoterResponse") + proto.RegisterType((*QueryVotesByProposalRequest)(nil), "regen.group.v1alpha1.QueryVotesByProposalRequest") + proto.RegisterType((*QueryVotesByProposalResponse)(nil), "regen.group.v1alpha1.QueryVotesByProposalResponse") + proto.RegisterType((*QueryVotesByVoterRequest)(nil), "regen.group.v1alpha1.QueryVotesByVoterRequest") + proto.RegisterType((*QueryVotesByVoterResponse)(nil), "regen.group.v1alpha1.QueryVotesByVoterResponse") + proto.RegisterType((*QueryPollRequest)(nil), "regen.group.v1alpha1.QueryPollRequest") + proto.RegisterType((*QueryPollResponse)(nil), "regen.group.v1alpha1.QueryPollResponse") + proto.RegisterType((*QueryPollsByGroupRequest)(nil), "regen.group.v1alpha1.QueryPollsByGroupRequest") + proto.RegisterType((*QueryPollsByGroupResponse)(nil), "regen.group.v1alpha1.QueryPollsByGroupResponse") + proto.RegisterType((*QueryPollsByCreatorRequest)(nil), "regen.group.v1alpha1.QueryPollsByCreatorRequest") + proto.RegisterType((*QueryPollsByCreatorResponse)(nil), "regen.group.v1alpha1.QueryPollsByCreatorResponse") + proto.RegisterType((*QueryVoteForPollByPollVoterRequest)(nil), "regen.group.v1alpha1.QueryVoteForPollByPollVoterRequest") + proto.RegisterType((*QueryVoteForPollByPollVoterResponse)(nil), "regen.group.v1alpha1.QueryVoteForPollByPollVoterResponse") + proto.RegisterType((*QueryVotesForPollByPollRequest)(nil), "regen.group.v1alpha1.QueryVotesForPollByPollRequest") + proto.RegisterType((*QueryVotesForPollByPollResponse)(nil), "regen.group.v1alpha1.QueryVotesForPollByPollResponse") + proto.RegisterType((*QueryVotesForPollByVoterRequest)(nil), "regen.group.v1alpha1.QueryVotesForPollByVoterRequest") + proto.RegisterType((*QueryVotesForPollByVoterResponse)(nil), "regen.group.v1alpha1.QueryVotesForPollByVoterResponse") +} + +func init() { proto.RegisterFile("regen/group/v1alpha1/query.proto", fileDescriptor_2523b81f3b315123) } + +var fileDescriptor_2523b81f3b315123 = []byte{ + // 1431 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0xcb, 0x6f, 0x1b, 0xd5, + 0x17, 0xce, 0xed, 0x2f, 0xcd, 0xe3, 0x24, 0xed, 0xaf, 0x5c, 0x42, 0x93, 0x0e, 0xc5, 0x49, 0xa6, + 0x21, 0x29, 0x4d, 0x32, 0x13, 0x3b, 0xcf, 0x26, 0x80, 0xa8, 0x23, 0xb5, 0xca, 0x22, 0x52, 0x71, + 0x25, 0xc4, 0x63, 0x81, 0x26, 0xf1, 0xd4, 0xb5, 0x88, 0x3d, 0xae, 0xc7, 0x89, 0x1a, 0x59, 0xe6, + 0x25, 0x51, 0xb6, 0x48, 0x48, 0x08, 0x10, 0x20, 0xba, 0x82, 0x4d, 0x37, 0x08, 0xd8, 0x20, 0x21, + 0xb1, 0x03, 0x56, 0x15, 0x6c, 0x58, 0x21, 0x94, 0xf0, 0x87, 0xa0, 0xb9, 0xf7, 0xcc, 0xcb, 0xbe, + 0xf3, 0x8a, 0x46, 0x49, 0x57, 0xf5, 0x9d, 0x9e, 0x73, 0xef, 0x77, 0xbe, 0x73, 0xee, 0x99, 0xf3, + 0x4d, 0x60, 0xac, 0xae, 0x97, 0xf4, 0xaa, 0x5a, 0xaa, 0x1b, 0xbb, 0x35, 0x75, 0x2f, 0xab, 0xed, + 0xd4, 0xee, 0x68, 0x59, 0xf5, 0xee, 0xae, 0x5e, 0xdf, 0x57, 0x6a, 0x75, 0xa3, 0x61, 0xd0, 0x21, + 0x66, 0xa1, 0x30, 0x0b, 0xc5, 0xb6, 0x90, 0xc4, 0x7e, 0x8d, 0xfd, 0x9a, 0x6e, 0x72, 0x3f, 0xe9, + 0x62, 0xc9, 0x30, 0x4a, 0x3b, 0xba, 0xaa, 0xd5, 0xca, 0xaa, 0x56, 0xad, 0x1a, 0x0d, 0xad, 0x51, + 0x36, 0xaa, 0xf6, 0xff, 0x0e, 0x95, 0x8c, 0x92, 0xc1, 0x7e, 0xaa, 0xd6, 0x2f, 0x7c, 0x7a, 0x65, + 0xdb, 0x30, 0x2b, 0x86, 0xa9, 0x6e, 0x69, 0xa6, 0xce, 0x41, 0xa8, 0x7b, 0xd9, 0x2d, 0xbd, 0xa1, + 0x65, 0xd5, 0x9a, 0x56, 0x2a, 0x57, 0xd9, 0x16, 0xdc, 0x56, 0xce, 0xc1, 0x53, 0x2f, 0x5b, 0x16, + 0x37, 0x2c, 0x08, 0x1b, 0xd5, 0xdb, 0x46, 0x41, 0xbf, 0xbb, 0xab, 0x9b, 0x0d, 0x7a, 0x01, 0xfa, + 0x18, 0xac, 0x37, 0xcb, 0xc5, 0x11, 0x32, 0x46, 0x2e, 0x77, 0x17, 0x7a, 0xd9, 0x7a, 0xa3, 0x28, + 0x6f, 0xc2, 0xf9, 0x76, 0x1f, 0xb3, 0x66, 0x54, 0x4d, 0x9d, 0xce, 0x43, 0x77, 0xb9, 0x7a, 0xdb, + 0x60, 0x0e, 0x03, 0xb9, 0x51, 0x45, 0x14, 0xb4, 0xe2, 0xba, 0x31, 0x63, 0x79, 0x05, 0x2e, 0xba, + 0xdb, 0x5d, 0xdb, 0xde, 0x36, 0x76, 0xab, 0x0d, 0x2f, 0x92, 0x11, 0xe8, 0xd5, 0x8a, 0xc5, 0xba, + 0x6e, 0x9a, 0x6c, 0xdf, 0xfe, 0x82, 0xbd, 0x94, 0xdf, 0x80, 0x67, 0x02, 0x3c, 0x11, 0xcf, 0xaa, + 0x0f, 0xcf, 0x64, 0x08, 0x1e, 0xaf, 0x37, 0x87, 0xd5, 0x82, 0x11, 0x77, 0xf3, 0x4d, 0xbd, 0xb2, + 0xa5, 0xd7, 0xcd, 0x68, 0x72, 0xe8, 0x75, 0x00, 0x97, 0xe4, 0x91, 0x53, 0x78, 0x30, 0xcf, 0x88, + 0x62, 0x65, 0x44, 0xe1, 0x65, 0x81, 0x19, 0x51, 0x6e, 0x6a, 0x25, 0x1d, 0xb7, 0x2d, 0x78, 0x3c, + 0xe5, 0x07, 0x04, 0x2e, 0x08, 0xce, 0xc7, 0xc0, 0xd6, 0xa0, 0xb7, 0xc2, 0x1f, 0x8d, 0x90, 0xb1, + 0xff, 0x5d, 0x1e, 0xc8, 0x8d, 0x87, 0xc4, 0xc6, 0x9d, 0x0b, 0xb6, 0x07, 0xbd, 0x21, 0x80, 0x38, + 0x15, 0x09, 0x91, 0x9f, 0xec, 0xc3, 0xb8, 0xef, 0x85, 0x68, 0xe6, 0xf7, 0xaf, 0x15, 0x2b, 0xe5, + 0xaa, 0xcd, 0xd1, 0x10, 0x9c, 0xd6, 0xac, 0x35, 0x26, 0x8d, 0x2f, 0x52, 0xa3, 0xe7, 0x2b, 0x02, + 0x92, 0xe8, 0x6c, 0xe4, 0x67, 0x19, 0x7a, 0x18, 0x13, 0x36, 0x3d, 0x91, 0xa5, 0x88, 0xe6, 0xe9, + 0x71, 0xf3, 0x01, 0x81, 0xb1, 0x8e, 0xe2, 0x34, 0xf3, 0x7c, 0x79, 0x8c, 0x75, 0xf4, 0x13, 0x81, + 0xf1, 0x10, 0x1c, 0xc8, 0xd7, 0x26, 0x9c, 0xe5, 0x40, 0x34, 0x34, 0x40, 0xde, 0xe2, 0x5e, 0x99, + 0x33, 0x25, 0xef, 0xee, 0xe9, 0xb1, 0xf8, 0x6e, 0x00, 0x8b, 0xc7, 0x58, 0x69, 0x41, 0x04, 0xfa, + 0x0b, 0xee, 0x71, 0x25, 0x70, 0x19, 0x86, 0x18, 0xf8, 0x9b, 0x75, 0xa3, 0x66, 0x98, 0xda, 0x8e, + 0xcd, 0xd9, 0x28, 0x0c, 0xd4, 0xf0, 0x91, 0x5b, 0x7c, 0x60, 0x3f, 0xda, 0x28, 0xca, 0xb7, 0xf0, + 0xc5, 0xe0, 0x3a, 0x3a, 0x3d, 0xb5, 0xcf, 0x36, 0xc3, 0xbe, 0x9a, 0x11, 0xc7, 0xe8, 0x78, 0x3a, + 0xf6, 0xf2, 0x87, 0x04, 0x2e, 0xf9, 0x76, 0xb5, 0x0b, 0x11, 0x03, 0x8f, 0x6c, 0xf9, 0xa9, 0x65, + 0xf5, 0x21, 0x81, 0x89, 0x70, 0x24, 0x18, 0xee, 0xf3, 0xd0, 0x6f, 0xc3, 0xb7, 0x73, 0x1a, 0x15, + 0xaf, 0xeb, 0x90, 0x5e, 0x1e, 0x5f, 0x85, 0x51, 0x06, 0xf7, 0x15, 0xa3, 0xa1, 0xe7, 0x1d, 0xd0, + 0xd6, 0xaa, 0x1e, 0x37, 0xa5, 0xd6, 0x3d, 0xd9, 0xb3, 0x1c, 0x18, 0x8e, 0xfe, 0x02, 0x5f, 0xc8, + 0x05, 0xbc, 0x61, 0xc2, 0x9d, 0x91, 0x04, 0x05, 0xba, 0x2d, 0x63, 0xcc, 0xb7, 0x24, 0x8e, 0xdf, + 0x72, 0x29, 0x30, 0x3b, 0xf9, 0x3e, 0x81, 0xa7, 0x9d, 0x4d, 0xcd, 0x7c, 0xe2, 0xea, 0x4b, 0x2d, + 0xcd, 0x9f, 0x11, 0x1c, 0x2e, 0x3a, 0x80, 0x60, 0x64, 0x73, 0x9c, 0x13, 0x3b, 0xb5, 0x61, 0xa1, + 0x71, 0xc3, 0xf4, 0x52, 0x7a, 0x0f, 0x07, 0x0c, 0x84, 0xe6, 0xcb, 0xa5, 0x93, 0x2a, 0xe2, 0x49, + 0x55, 0x6a, 0xac, 0x7c, 0x62, 0xcf, 0x16, 0xfe, 0xa3, 0x4f, 0x9e, 0x92, 0x69, 0x38, 0xc7, 0x2f, + 0xa5, 0xb1, 0xe3, 0xd4, 0xca, 0x30, 0xf4, 0xd6, 0x8c, 0x1d, 0x4f, 0x9d, 0xf4, 0x58, 0xcb, 0x8d, + 0xa2, 0xbc, 0x0e, 0x4f, 0x78, 0x8c, 0xdd, 0x4a, 0xb5, 0xfe, 0x3b, 0xbc, 0x52, 0x99, 0x07, 0xb3, + 0x73, 0xa6, 0x3c, 0xeb, 0xd1, 0x09, 0xbc, 0x9d, 0x9d, 0x4c, 0xf8, 0xcf, 0x77, 0x33, 0x61, 0x81, + 0x8c, 0xc8, 0x04, 0x8b, 0x86, 0x1b, 0xa6, 0x97, 0x89, 0xb7, 0x71, 0xbc, 0x42, 0x5c, 0xeb, 0x75, + 0x5d, 0x6b, 0x18, 0x75, 0x4f, 0x7f, 0xde, 0xe6, 0x4f, 0xec, 0xfe, 0x8c, 0xcb, 0xd4, 0x88, 0xf9, + 0xd4, 0xee, 0x20, 0xed, 0x00, 0x4e, 0x9e, 0x9a, 0x5b, 0x20, 0x3b, 0x97, 0xe7, 0xba, 0x51, 0xb7, + 0xce, 0xc8, 0x33, 0x98, 0xbe, 0x1b, 0x1c, 0x54, 0xb6, 0x01, 0x5d, 0xf8, 0x35, 0x7c, 0x31, 0x06, + 0x6d, 0x8a, 0x61, 0xe7, 0x7c, 0x8d, 0x38, 0x13, 0x7c, 0x35, 0x79, 0x89, 0xb3, 0x66, 0xfc, 0x1e, + 0x81, 0x8c, 0x7b, 0xdb, 0x7d, 0x9b, 0x47, 0x82, 0x4d, 0x2b, 0x9d, 0x5f, 0x13, 0xcf, 0xfb, 0xab, + 0x1d, 0x03, 0xc6, 0xb6, 0xe0, 0xef, 0x3b, 0x51, 0xc1, 0xa5, 0xdd, 0x7b, 0xde, 0x11, 0x22, 0x3c, + 0xc6, 0xae, 0xfc, 0x80, 0x78, 0xde, 0xc4, 0x1d, 0x08, 0x1e, 0x0b, 0x92, 0x72, 0x7f, 0x0f, 0xc3, + 0x69, 0x86, 0x91, 0x7e, 0x41, 0xa0, 0xdf, 0x91, 0x4f, 0x74, 0x5a, 0x8c, 0x43, 0xf8, 0x69, 0x41, + 0x9a, 0x89, 0x67, 0xcc, 0x8f, 0x97, 0x17, 0xde, 0xff, 0xf3, 0xdf, 0x8f, 0x4f, 0x29, 0x74, 0x46, + 0x15, 0x7e, 0x2c, 0xe1, 0xba, 0x4d, 0x6d, 0xda, 0x9d, 0xba, 0xa5, 0x5a, 0xea, 0x9d, 0x7e, 0x4f, + 0xe0, 0x5c, 0xfb, 0x90, 0x4d, 0x73, 0x51, 0x07, 0x77, 0x7e, 0x7d, 0x90, 0xe6, 0x13, 0xf9, 0x20, + 0xe6, 0x65, 0x86, 0x39, 0x4b, 0xd5, 0x50, 0xcc, 0xb6, 0x54, 0x50, 0x9b, 0x38, 0xdd, 0xb6, 0xe8, + 0xb7, 0x04, 0x06, 0xbd, 0x82, 0x9f, 0x2a, 0x51, 0xc7, 0xfb, 0xbf, 0x4c, 0x48, 0x6a, 0x6c, 0xfb, + 0x44, 0x50, 0x3d, 0xf4, 0xda, 0x5f, 0x11, 0xbe, 0x21, 0x70, 0xc6, 0x27, 0xbe, 0x69, 0xe4, 0xd9, + 0x6d, 0xc2, 0x4d, 0x9a, 0x8b, 0xef, 0x80, 0x68, 0xe7, 0x19, 0xda, 0x59, 0x3a, 0x1d, 0x4e, 0xac, + 0xe5, 0xc3, 0x68, 0xad, 0x94, 0xab, 0x2d, 0xfa, 0x0b, 0x81, 0x21, 0x91, 0xfa, 0xa5, 0x4b, 0x31, + 0x73, 0xdb, 0x36, 0x18, 0x48, 0xcb, 0x89, 0xfd, 0x10, 0xfe, 0x0a, 0x83, 0x9f, 0xa3, 0x73, 0x71, + 0xc9, 0xb6, 0x4b, 0x84, 0xfe, 0xdc, 0x19, 0x03, 0x27, 0x3d, 0x41, 0x0c, 0x3e, 0xee, 0x97, 0x13, + 0xfb, 0x61, 0x0c, 0x8b, 0x2c, 0x06, 0x95, 0xce, 0x8a, 0x63, 0xf0, 0x73, 0xef, 0x06, 0xf0, 0x39, + 0x81, 0x3e, 0x7b, 0xfa, 0xa6, 0x57, 0x42, 0x0e, 0x6f, 0xd3, 0x0a, 0xd2, 0x74, 0x2c, 0xdb, 0x78, + 0xe0, 0x1c, 0x61, 0xa6, 0x36, 0x3d, 0xfa, 0xa3, 0x45, 0xff, 0x20, 0x30, 0x1c, 0x20, 0x04, 0xe9, + 0xd5, 0x18, 0xe7, 0x8b, 0x65, 0xac, 0xb4, 0x7a, 0x14, 0x57, 0x8c, 0xe4, 0x25, 0x16, 0xc9, 0x2a, + 0x5d, 0x09, 0x29, 0x95, 0xd9, 0xce, 0x0e, 0xe2, 0x86, 0x48, 0x7f, 0x23, 0xf0, 0xa4, 0x40, 0xd4, + 0xd1, 0xc5, 0x10, 0x54, 0xc1, 0xf2, 0x52, 0x5a, 0x4a, 0xea, 0x86, 0x81, 0xac, 0xb3, 0x40, 0x5e, + 0xa0, 0x6b, 0x89, 0x52, 0xa2, 0xb2, 0x17, 0x97, 0xda, 0x64, 0xaf, 0xd8, 0x16, 0xfd, 0x81, 0xc0, + 0xff, 0xdb, 0x24, 0x1c, 0xcd, 0x46, 0x00, 0xea, 0xd4, 0x9d, 0x52, 0x2e, 0x89, 0x0b, 0xe2, 0x5f, + 0x63, 0xf8, 0x17, 0xe9, 0xfc, 0x11, 0xf0, 0xd3, 0x2f, 0x09, 0x0c, 0x7a, 0x45, 0x56, 0x68, 0x3f, + 0x17, 0x08, 0xc1, 0xd0, 0x7e, 0x2e, 0x52, 0x6f, 0xf2, 0x0c, 0x83, 0x3b, 0x49, 0x27, 0xc4, 0x70, + 0x19, 0x9f, 0x2e, 0xaf, 0xf7, 0x09, 0x74, 0x5b, 0x83, 0x02, 0x9d, 0x0c, 0x2b, 0x55, 0x77, 0x52, + 0x94, 0xa6, 0x22, 0xed, 0x10, 0xc7, 0x2c, 0xc3, 0x31, 0x45, 0x9f, 0x0d, 0xa0, 0xcd, 0x9a, 0xc9, + 0xd5, 0x26, 0x4e, 0x9d, 0x2d, 0xab, 0x3d, 0x0c, 0x7a, 0x35, 0x50, 0x28, 0x51, 0x02, 0xb1, 0x16, + 0x4a, 0x94, 0x48, 0x5c, 0xc9, 0xcf, 0x31, 0x80, 0x97, 0xe8, 0x78, 0xc8, 0x05, 0xe3, 0x30, 0xe9, + 0x43, 0x02, 0x67, 0xfd, 0x3a, 0x84, 0xce, 0x45, 0x1f, 0xe7, 0xd7, 0x4c, 0x52, 0x36, 0x81, 0x07, + 0x42, 0x5c, 0x62, 0x10, 0xe7, 0xa8, 0x22, 0x86, 0x88, 0x9a, 0xcb, 0x54, 0x9b, 0xf8, 0xab, 0x85, + 0x78, 0x7f, 0x27, 0x70, 0x5e, 0x2c, 0x24, 0xe8, 0x4a, 0x44, 0x3d, 0x05, 0x0a, 0x1a, 0xe9, 0xea, + 0x11, 0x3c, 0x63, 0x5e, 0x21, 0x7f, 0x2d, 0xb4, 0x5d, 0xfd, 0x1f, 0x09, 0xd0, 0x4e, 0xd5, 0x40, + 0x17, 0xa2, 0x2e, 0x86, 0x48, 0xe8, 0x48, 0x8b, 0x09, 0xbd, 0xe2, 0x8d, 0x1d, 0xc2, 0x00, 0xe8, + 0x77, 0xd8, 0x7f, 0xdb, 0x46, 0x79, 0x1a, 0x1f, 0x43, 0xa2, 0xfe, 0x1b, 0xa0, 0x18, 0x92, 0x35, + 0x84, 0xfc, 0x8b, 0xbf, 0x1e, 0x64, 0xc8, 0xa3, 0x83, 0x0c, 0xf9, 0xe7, 0x20, 0x43, 0x3e, 0x3a, + 0xcc, 0x74, 0x3d, 0x3a, 0xcc, 0x74, 0xfd, 0x75, 0x98, 0xe9, 0x7a, 0x7d, 0xa2, 0x54, 0x6e, 0xdc, + 0xd9, 0xdd, 0x52, 0xb6, 0x8d, 0x8a, 0x8a, 0x7f, 0x60, 0xe4, 0xff, 0xcc, 0x9a, 0xc5, 0xb7, 0xd4, + 0x7b, 0x7c, 0xdf, 0xad, 0x1e, 0xf6, 0x67, 0xc5, 0xf9, 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0xc4, + 0xd7, 0x49, 0x00, 0x12, 0x1d, 0x00, 0x00, +} + +// 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 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + // GroupInfo queries group info based on group id. + GroupInfo(ctx context.Context, in *QueryGroupInfoRequest, opts ...grpc.CallOption) (*QueryGroupInfoResponse, error) + // GroupAccountInfo queries group account info based on group account address. + GroupAccountInfo(ctx context.Context, in *QueryGroupAccountInfoRequest, opts ...grpc.CallOption) (*QueryGroupAccountInfoResponse, error) + // GroupMembers queries members of a group + GroupMembers(ctx context.Context, in *QueryGroupMembersRequest, opts ...grpc.CallOption) (*QueryGroupMembersResponse, error) + // GroupsByAdmin queries groups by admin address. + GroupsByAdmin(ctx context.Context, in *QueryGroupsByAdminRequest, opts ...grpc.CallOption) (*QueryGroupsByAdminResponse, error) + // GroupAccountsByGroup queries group accounts by group id. + GroupAccountsByGroup(ctx context.Context, in *QueryGroupAccountsByGroupRequest, opts ...grpc.CallOption) (*QueryGroupAccountsByGroupResponse, error) + // GroupsByAdmin queries group accounts by admin address. + GroupAccountsByAdmin(ctx context.Context, in *QueryGroupAccountsByAdminRequest, opts ...grpc.CallOption) (*QueryGroupAccountsByAdminResponse, error) + // Proposal queries a proposal based on proposal id. + Proposal(ctx context.Context, in *QueryProposalRequest, opts ...grpc.CallOption) (*QueryProposalResponse, error) + // ProposalsByGroupAccount queries proposals based on group account address. + ProposalsByGroupAccount(ctx context.Context, in *QueryProposalsByGroupAccountRequest, opts ...grpc.CallOption) (*QueryProposalsByGroupAccountResponse, error) + // VoteByProposalVoter queries a vote by proposal id and voter. + VoteByProposalVoter(ctx context.Context, in *QueryVoteByProposalVoterRequest, opts ...grpc.CallOption) (*QueryVoteByProposalVoterResponse, error) + // VotesByProposal queries a vote by proposal. + VotesByProposal(ctx context.Context, in *QueryVotesByProposalRequest, opts ...grpc.CallOption) (*QueryVotesByProposalResponse, error) + // VotesByVoter queries a vote by voter. + VotesByVoter(ctx context.Context, in *QueryVotesByVoterRequest, opts ...grpc.CallOption) (*QueryVotesByVoterResponse, error) + // Poll queries a poll based on poll id. + Poll(ctx context.Context, in *QueryPollRequest, opts ...grpc.CallOption) (*QueryPollResponse, error) + // PollsByGroup queries polls based on group id. + PollsByGroup(ctx context.Context, in *QueryPollsByGroupRequest, opts ...grpc.CallOption) (*QueryPollsByGroupResponse, error) + // PollsByCreator queries polls by creator address. + PollsByCreator(ctx context.Context, in *QueryPollsByCreatorRequest, opts ...grpc.CallOption) (*QueryPollsByCreatorResponse, error) + // VoteForPollByPollVoter queries a vote by poll id and voter. + VoteForPollByPollVoter(ctx context.Context, in *QueryVoteForPollByPollVoterRequest, opts ...grpc.CallOption) (*QueryVoteForPollByPollVoterResponse, error) + // VotesForPollByPoll queries votes by poll. + VotesForPollByPoll(ctx context.Context, in *QueryVotesForPollByPollRequest, opts ...grpc.CallOption) (*QueryVotesForPollByPollResponse, error) + // VotesForPollByVoter queries votes for poll by voter. + VotesForPollByVoter(ctx context.Context, in *QueryVotesForPollByVoterRequest, opts ...grpc.CallOption) (*QueryVotesForPollByVoterResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) GroupInfo(ctx context.Context, in *QueryGroupInfoRequest, opts ...grpc.CallOption) (*QueryGroupInfoResponse, error) { + out := new(QueryGroupInfoResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/GroupInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GroupAccountInfo(ctx context.Context, in *QueryGroupAccountInfoRequest, opts ...grpc.CallOption) (*QueryGroupAccountInfoResponse, error) { + out := new(QueryGroupAccountInfoResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/GroupAccountInfo", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GroupMembers(ctx context.Context, in *QueryGroupMembersRequest, opts ...grpc.CallOption) (*QueryGroupMembersResponse, error) { + out := new(QueryGroupMembersResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/GroupMembers", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GroupsByAdmin(ctx context.Context, in *QueryGroupsByAdminRequest, opts ...grpc.CallOption) (*QueryGroupsByAdminResponse, error) { + out := new(QueryGroupsByAdminResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/GroupsByAdmin", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GroupAccountsByGroup(ctx context.Context, in *QueryGroupAccountsByGroupRequest, opts ...grpc.CallOption) (*QueryGroupAccountsByGroupResponse, error) { + out := new(QueryGroupAccountsByGroupResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/GroupAccountsByGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) GroupAccountsByAdmin(ctx context.Context, in *QueryGroupAccountsByAdminRequest, opts ...grpc.CallOption) (*QueryGroupAccountsByAdminResponse, error) { + out := new(QueryGroupAccountsByAdminResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/GroupAccountsByAdmin", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Proposal(ctx context.Context, in *QueryProposalRequest, opts ...grpc.CallOption) (*QueryProposalResponse, error) { + out := new(QueryProposalResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/Proposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) ProposalsByGroupAccount(ctx context.Context, in *QueryProposalsByGroupAccountRequest, opts ...grpc.CallOption) (*QueryProposalsByGroupAccountResponse, error) { + out := new(QueryProposalsByGroupAccountResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/ProposalsByGroupAccount", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VoteByProposalVoter(ctx context.Context, in *QueryVoteByProposalVoterRequest, opts ...grpc.CallOption) (*QueryVoteByProposalVoterResponse, error) { + out := new(QueryVoteByProposalVoterResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/VoteByProposalVoter", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VotesByProposal(ctx context.Context, in *QueryVotesByProposalRequest, opts ...grpc.CallOption) (*QueryVotesByProposalResponse, error) { + out := new(QueryVotesByProposalResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/VotesByProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VotesByVoter(ctx context.Context, in *QueryVotesByVoterRequest, opts ...grpc.CallOption) (*QueryVotesByVoterResponse, error) { + out := new(QueryVotesByVoterResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/VotesByVoter", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) Poll(ctx context.Context, in *QueryPollRequest, opts ...grpc.CallOption) (*QueryPollResponse, error) { + out := new(QueryPollResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/Poll", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) PollsByGroup(ctx context.Context, in *QueryPollsByGroupRequest, opts ...grpc.CallOption) (*QueryPollsByGroupResponse, error) { + out := new(QueryPollsByGroupResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/PollsByGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) PollsByCreator(ctx context.Context, in *QueryPollsByCreatorRequest, opts ...grpc.CallOption) (*QueryPollsByCreatorResponse, error) { + out := new(QueryPollsByCreatorResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/PollsByCreator", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VoteForPollByPollVoter(ctx context.Context, in *QueryVoteForPollByPollVoterRequest, opts ...grpc.CallOption) (*QueryVoteForPollByPollVoterResponse, error) { + out := new(QueryVoteForPollByPollVoterResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/VoteForPollByPollVoter", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VotesForPollByPoll(ctx context.Context, in *QueryVotesForPollByPollRequest, opts ...grpc.CallOption) (*QueryVotesForPollByPollResponse, error) { + out := new(QueryVotesForPollByPollResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/VotesForPollByPoll", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *queryClient) VotesForPollByVoter(ctx context.Context, in *QueryVotesForPollByVoterRequest, opts ...grpc.CallOption) (*QueryVotesForPollByVoterResponse, error) { + out := new(QueryVotesForPollByVoterResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Query/VotesForPollByVoter", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + // GroupInfo queries group info based on group id. + GroupInfo(context.Context, *QueryGroupInfoRequest) (*QueryGroupInfoResponse, error) + // GroupAccountInfo queries group account info based on group account address. + GroupAccountInfo(context.Context, *QueryGroupAccountInfoRequest) (*QueryGroupAccountInfoResponse, error) + // GroupMembers queries members of a group + GroupMembers(context.Context, *QueryGroupMembersRequest) (*QueryGroupMembersResponse, error) + // GroupsByAdmin queries groups by admin address. + GroupsByAdmin(context.Context, *QueryGroupsByAdminRequest) (*QueryGroupsByAdminResponse, error) + // GroupAccountsByGroup queries group accounts by group id. + GroupAccountsByGroup(context.Context, *QueryGroupAccountsByGroupRequest) (*QueryGroupAccountsByGroupResponse, error) + // GroupsByAdmin queries group accounts by admin address. + GroupAccountsByAdmin(context.Context, *QueryGroupAccountsByAdminRequest) (*QueryGroupAccountsByAdminResponse, error) + // Proposal queries a proposal based on proposal id. + Proposal(context.Context, *QueryProposalRequest) (*QueryProposalResponse, error) + // ProposalsByGroupAccount queries proposals based on group account address. + ProposalsByGroupAccount(context.Context, *QueryProposalsByGroupAccountRequest) (*QueryProposalsByGroupAccountResponse, error) + // VoteByProposalVoter queries a vote by proposal id and voter. + VoteByProposalVoter(context.Context, *QueryVoteByProposalVoterRequest) (*QueryVoteByProposalVoterResponse, error) + // VotesByProposal queries a vote by proposal. + VotesByProposal(context.Context, *QueryVotesByProposalRequest) (*QueryVotesByProposalResponse, error) + // VotesByVoter queries a vote by voter. + VotesByVoter(context.Context, *QueryVotesByVoterRequest) (*QueryVotesByVoterResponse, error) + // Poll queries a poll based on poll id. + Poll(context.Context, *QueryPollRequest) (*QueryPollResponse, error) + // PollsByGroup queries polls based on group id. + PollsByGroup(context.Context, *QueryPollsByGroupRequest) (*QueryPollsByGroupResponse, error) + // PollsByCreator queries polls by creator address. + PollsByCreator(context.Context, *QueryPollsByCreatorRequest) (*QueryPollsByCreatorResponse, error) + // VoteForPollByPollVoter queries a vote by poll id and voter. + VoteForPollByPollVoter(context.Context, *QueryVoteForPollByPollVoterRequest) (*QueryVoteForPollByPollVoterResponse, error) + // VotesForPollByPoll queries votes by poll. + VotesForPollByPoll(context.Context, *QueryVotesForPollByPollRequest) (*QueryVotesForPollByPollResponse, error) + // VotesForPollByVoter queries votes for poll by voter. + VotesForPollByVoter(context.Context, *QueryVotesForPollByVoterRequest) (*QueryVotesForPollByVoterResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) GroupInfo(ctx context.Context, req *QueryGroupInfoRequest) (*QueryGroupInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GroupInfo not implemented") +} +func (*UnimplementedQueryServer) GroupAccountInfo(ctx context.Context, req *QueryGroupAccountInfoRequest) (*QueryGroupAccountInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GroupAccountInfo not implemented") +} +func (*UnimplementedQueryServer) GroupMembers(ctx context.Context, req *QueryGroupMembersRequest) (*QueryGroupMembersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GroupMembers not implemented") +} +func (*UnimplementedQueryServer) GroupsByAdmin(ctx context.Context, req *QueryGroupsByAdminRequest) (*QueryGroupsByAdminResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GroupsByAdmin not implemented") +} +func (*UnimplementedQueryServer) GroupAccountsByGroup(ctx context.Context, req *QueryGroupAccountsByGroupRequest) (*QueryGroupAccountsByGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GroupAccountsByGroup not implemented") +} +func (*UnimplementedQueryServer) GroupAccountsByAdmin(ctx context.Context, req *QueryGroupAccountsByAdminRequest) (*QueryGroupAccountsByAdminResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GroupAccountsByAdmin not implemented") +} +func (*UnimplementedQueryServer) Proposal(ctx context.Context, req *QueryProposalRequest) (*QueryProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Proposal not implemented") +} +func (*UnimplementedQueryServer) ProposalsByGroupAccount(ctx context.Context, req *QueryProposalsByGroupAccountRequest) (*QueryProposalsByGroupAccountResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ProposalsByGroupAccount not implemented") +} +func (*UnimplementedQueryServer) VoteByProposalVoter(ctx context.Context, req *QueryVoteByProposalVoterRequest) (*QueryVoteByProposalVoterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteByProposalVoter not implemented") +} +func (*UnimplementedQueryServer) VotesByProposal(ctx context.Context, req *QueryVotesByProposalRequest) (*QueryVotesByProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VotesByProposal not implemented") +} +func (*UnimplementedQueryServer) VotesByVoter(ctx context.Context, req *QueryVotesByVoterRequest) (*QueryVotesByVoterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VotesByVoter not implemented") +} +func (*UnimplementedQueryServer) Poll(ctx context.Context, req *QueryPollRequest) (*QueryPollResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Poll not implemented") +} +func (*UnimplementedQueryServer) PollsByGroup(ctx context.Context, req *QueryPollsByGroupRequest) (*QueryPollsByGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PollsByGroup not implemented") +} +func (*UnimplementedQueryServer) PollsByCreator(ctx context.Context, req *QueryPollsByCreatorRequest) (*QueryPollsByCreatorResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PollsByCreator not implemented") +} +func (*UnimplementedQueryServer) VoteForPollByPollVoter(ctx context.Context, req *QueryVoteForPollByPollVoterRequest) (*QueryVoteForPollByPollVoterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteForPollByPollVoter not implemented") +} +func (*UnimplementedQueryServer) VotesForPollByPoll(ctx context.Context, req *QueryVotesForPollByPollRequest) (*QueryVotesForPollByPollResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VotesForPollByPoll not implemented") +} +func (*UnimplementedQueryServer) VotesForPollByVoter(ctx context.Context, req *QueryVotesForPollByVoterRequest) (*QueryVotesForPollByVoterResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VotesForPollByVoter not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_GroupInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GroupInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/GroupInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GroupInfo(ctx, req.(*QueryGroupInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_GroupAccountInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupAccountInfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GroupAccountInfo(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/GroupAccountInfo", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GroupAccountInfo(ctx, req.(*QueryGroupAccountInfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_GroupMembers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupMembersRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GroupMembers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/GroupMembers", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GroupMembers(ctx, req.(*QueryGroupMembersRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_GroupsByAdmin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupsByAdminRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GroupsByAdmin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/GroupsByAdmin", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GroupsByAdmin(ctx, req.(*QueryGroupsByAdminRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_GroupAccountsByGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupAccountsByGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GroupAccountsByGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/GroupAccountsByGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GroupAccountsByGroup(ctx, req.(*QueryGroupAccountsByGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_GroupAccountsByAdmin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryGroupAccountsByAdminRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).GroupAccountsByAdmin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/GroupAccountsByAdmin", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).GroupAccountsByAdmin(ctx, req.(*QueryGroupAccountsByAdminRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Proposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryProposalRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Proposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/Proposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Proposal(ctx, req.(*QueryProposalRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_ProposalsByGroupAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryProposalsByGroupAccountRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).ProposalsByGroupAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/ProposalsByGroupAccount", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).ProposalsByGroupAccount(ctx, req.(*QueryProposalsByGroupAccountRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VoteByProposalVoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVoteByProposalVoterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VoteByProposalVoter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/VoteByProposalVoter", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VoteByProposalVoter(ctx, req.(*QueryVoteByProposalVoterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VotesByProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVotesByProposalRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VotesByProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/VotesByProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VotesByProposal(ctx, req.(*QueryVotesByProposalRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VotesByVoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVotesByVoterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VotesByVoter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/VotesByVoter", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VotesByVoter(ctx, req.(*QueryVotesByVoterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_Poll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPollRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Poll(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/Poll", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Poll(ctx, req.(*QueryPollRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_PollsByGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPollsByGroupRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).PollsByGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/PollsByGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).PollsByGroup(ctx, req.(*QueryPollsByGroupRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_PollsByCreator_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPollsByCreatorRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).PollsByCreator(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/PollsByCreator", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).PollsByCreator(ctx, req.(*QueryPollsByCreatorRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VoteForPollByPollVoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVoteForPollByPollVoterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VoteForPollByPollVoter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/VoteForPollByPollVoter", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VoteForPollByPollVoter(ctx, req.(*QueryVoteForPollByPollVoterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VotesForPollByPoll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVotesForPollByPollRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VotesForPollByPoll(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/VotesForPollByPoll", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VotesForPollByPoll(ctx, req.(*QueryVotesForPollByPollRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Query_VotesForPollByVoter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryVotesForPollByVoterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).VotesForPollByVoter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Query/VotesForPollByVoter", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).VotesForPollByVoter(ctx, req.(*QueryVotesForPollByVoterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "regen.group.v1alpha1.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GroupInfo", + Handler: _Query_GroupInfo_Handler, + }, + { + MethodName: "GroupAccountInfo", + Handler: _Query_GroupAccountInfo_Handler, + }, + { + MethodName: "GroupMembers", + Handler: _Query_GroupMembers_Handler, + }, + { + MethodName: "GroupsByAdmin", + Handler: _Query_GroupsByAdmin_Handler, + }, + { + MethodName: "GroupAccountsByGroup", + Handler: _Query_GroupAccountsByGroup_Handler, + }, + { + MethodName: "GroupAccountsByAdmin", + Handler: _Query_GroupAccountsByAdmin_Handler, + }, + { + MethodName: "Proposal", + Handler: _Query_Proposal_Handler, + }, + { + MethodName: "ProposalsByGroupAccount", + Handler: _Query_ProposalsByGroupAccount_Handler, + }, + { + MethodName: "VoteByProposalVoter", + Handler: _Query_VoteByProposalVoter_Handler, + }, + { + MethodName: "VotesByProposal", + Handler: _Query_VotesByProposal_Handler, + }, + { + MethodName: "VotesByVoter", + Handler: _Query_VotesByVoter_Handler, + }, + { + MethodName: "Poll", + Handler: _Query_Poll_Handler, + }, + { + MethodName: "PollsByGroup", + Handler: _Query_PollsByGroup_Handler, + }, + { + MethodName: "PollsByCreator", + Handler: _Query_PollsByCreator_Handler, + }, + { + MethodName: "VoteForPollByPollVoter", + Handler: _Query_VoteForPollByPollVoter_Handler, + }, + { + MethodName: "VotesForPollByPoll", + Handler: _Query_VotesForPollByPoll_Handler, + }, + { + MethodName: "VotesForPollByVoter", + Handler: _Query_VotesForPollByVoter_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "regen/group/v1alpha1/query.proto", +} + +func (m *QueryGroupInfoRequest) 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 *QueryGroupInfoRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupInfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GroupId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupInfoResponse) 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 *QueryGroupInfoResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupInfoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupAccountInfoRequest) 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 *QueryGroupAccountInfoRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupAccountInfoRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupAccountInfoResponse) 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 *QueryGroupAccountInfoResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupAccountInfoResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Info != nil { + { + size, err := m.Info.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupMembersRequest) 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 *QueryGroupMembersRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupMembersRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupMembersResponse) 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 *QueryGroupMembersResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupMembersResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Members[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupsByAdminRequest) 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 *QueryGroupsByAdminRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupsByAdminRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupsByAdminResponse) 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 *QueryGroupsByAdminResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupsByAdminResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Groups) > 0 { + for iNdEx := len(m.Groups) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Groups[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupAccountsByGroupRequest) 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 *QueryGroupAccountsByGroupRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupAccountsByGroupRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupAccountsByGroupResponse) 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 *QueryGroupAccountsByGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupAccountsByGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.GroupAccounts) > 0 { + for iNdEx := len(m.GroupAccounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.GroupAccounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupAccountsByAdminRequest) 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 *QueryGroupAccountsByAdminRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupAccountsByAdminRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryGroupAccountsByAdminResponse) 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 *QueryGroupAccountsByAdminResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryGroupAccountsByAdminResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.GroupAccounts) > 0 { + for iNdEx := len(m.GroupAccounts) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.GroupAccounts[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryProposalRequest) 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 *QueryProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryProposalResponse) 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 *QueryProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Proposal != nil { + { + size, err := m.Proposal.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryProposalsByGroupAccountRequest) 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 *QueryProposalsByGroupAccountRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalsByGroupAccountRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryProposalsByGroupAccountResponse) 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 *QueryProposalsByGroupAccountResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryProposalsByGroupAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Proposals) > 0 { + for iNdEx := len(m.Proposals) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Proposals[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteByProposalVoterRequest) 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 *QueryVoteByProposalVoterRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteByProposalVoterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteByProposalVoterResponse) 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 *QueryVoteByProposalVoterResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteByProposalVoterResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesByProposalRequest) 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 *QueryVotesByProposalRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesByProposalRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesByProposalResponse) 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 *QueryVotesByProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesByProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesByVoterRequest) 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 *QueryVotesByVoterRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesByVoterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesByVoterResponse) 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 *QueryVotesByVoterResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesByVoterResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryPollRequest) 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 *QueryPollRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPollRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PollId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryPollResponse) 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 *QueryPollResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPollResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Poll != nil { + { + size, err := m.Poll.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryPollsByGroupRequest) 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 *QueryPollsByGroupRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPollsByGroupRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryPollsByGroupResponse) 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 *QueryPollsByGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPollsByGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Polls) > 0 { + for iNdEx := len(m.Polls) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Polls[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryPollsByCreatorRequest) 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 *QueryPollsByCreatorRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPollsByCreatorRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryPollsByCreatorResponse) 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 *QueryPollsByCreatorResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPollsByCreatorResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Polls) > 0 { + for iNdEx := len(m.Polls) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Polls[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteForPollByPollVoterRequest) 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 *QueryVoteForPollByPollVoterRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteForPollByPollVoterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.PollId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVoteForPollByPollVoterResponse) 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 *QueryVoteForPollByPollVoterResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVoteForPollByPollVoterResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Vote != nil { + { + size, err := m.Vote.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesForPollByPollRequest) 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 *QueryVotesForPollByPollRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesForPollByPollRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.PollId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesForPollByPollResponse) 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 *QueryVotesForPollByPollResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesForPollByPollResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesForPollByVoterRequest) 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 *QueryVotesForPollByVoterRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesForPollByVoterRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryVotesForPollByVoterResponse) 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 *QueryVotesForPollByVoterResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryVotesForPollByVoterResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QueryGroupInfoRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovQuery(uint64(m.GroupId)) + } + return n +} + +func (m *QueryGroupInfoResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupAccountInfoRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupAccountInfoResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Info != nil { + l = m.Info.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupMembersRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovQuery(uint64(m.GroupId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupMembersResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Members) > 0 { + for _, e := range m.Members { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupsByAdminRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupsByAdminResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Groups) > 0 { + for _, e := range m.Groups { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupAccountsByGroupRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovQuery(uint64(m.GroupId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupAccountsByGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.GroupAccounts) > 0 { + for _, e := range m.GroupAccounts { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupAccountsByAdminRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryGroupAccountsByAdminResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.GroupAccounts) > 0 { + for _, e := range m.GroupAccounts { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + return n +} + +func (m *QueryProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Proposal != nil { + l = m.Proposal.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryProposalsByGroupAccountRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryProposalsByGroupAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Proposals) > 0 { + for _, e := range m.Proposals { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVoteByProposalVoterRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVoteByProposalVoterResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesByProposalRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovQuery(uint64(m.ProposalId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesByProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesByVoterRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesByVoterResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPollRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovQuery(uint64(m.PollId)) + } + return n +} + +func (m *QueryPollResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Poll != nil { + l = m.Poll.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPollsByGroupRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovQuery(uint64(m.GroupId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPollsByGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Polls) > 0 { + for _, e := range m.Polls { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPollsByCreatorRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPollsByCreatorResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Polls) > 0 { + for _, e := range m.Polls { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVoteForPollByPollVoterRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovQuery(uint64(m.PollId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVoteForPollByPollVoterResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Vote != nil { + l = m.Vote.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesForPollByPollRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovQuery(uint64(m.PollId)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesForPollByPollResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesForPollByVoterRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryVotesForPollByVoterResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QueryGroupInfoRequest) 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 ErrIntOverflowQuery + } + 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: QueryGroupInfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupInfoResponse) 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 ErrIntOverflowQuery + } + 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: QueryGroupInfoResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Info == nil { + m.Info = &GroupInfo{} + } + if err := m.Info.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupAccountInfoRequest) 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 ErrIntOverflowQuery + } + 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: QueryGroupAccountInfoRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupAccountInfoRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupAccountInfoResponse) 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 ErrIntOverflowQuery + } + 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: QueryGroupAccountInfoResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupAccountInfoResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Info", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Info == nil { + m.Info = &GroupAccountInfo{} + } + if err := m.Info.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupMembersRequest) 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 ErrIntOverflowQuery + } + 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: QueryGroupMembersRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupMembersRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupMembersResponse) 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 ErrIntOverflowQuery + } + 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: QueryGroupMembersResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupMembersResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, &GroupMember{}) + if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupsByAdminRequest) 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 ErrIntOverflowQuery + } + 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: QueryGroupsByAdminRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupsByAdminRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupsByAdminResponse) 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 ErrIntOverflowQuery + } + 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: QueryGroupsByAdminResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupsByAdminResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Groups", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Groups = append(m.Groups, &GroupInfo{}) + if err := m.Groups[len(m.Groups)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupAccountsByGroupRequest) 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 ErrIntOverflowQuery + } + 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: QueryGroupAccountsByGroupRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupAccountsByGroupRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupAccountsByGroupResponse) 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 ErrIntOverflowQuery + } + 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: QueryGroupAccountsByGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupAccountsByGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupAccounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GroupAccounts = append(m.GroupAccounts, &GroupAccountInfo{}) + if err := m.GroupAccounts[len(m.GroupAccounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupAccountsByAdminRequest) 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 ErrIntOverflowQuery + } + 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: QueryGroupAccountsByAdminRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupAccountsByAdminRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryGroupAccountsByAdminResponse) 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 ErrIntOverflowQuery + } + 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: QueryGroupAccountsByAdminResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryGroupAccountsByAdminResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupAccounts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.GroupAccounts = append(m.GroupAccounts, &GroupAccountInfo{}) + if err := m.GroupAccounts[len(m.GroupAccounts)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryProposalRequest) 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 ErrIntOverflowQuery + } + 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: QueryProposalRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryProposalResponse) 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 ErrIntOverflowQuery + } + 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: QueryProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposal", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Proposal == nil { + m.Proposal = &Proposal{} + } + if err := m.Proposal.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryProposalsByGroupAccountRequest) 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 ErrIntOverflowQuery + } + 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: QueryProposalsByGroupAccountRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalsByGroupAccountRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryProposalsByGroupAccountResponse) 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 ErrIntOverflowQuery + } + 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: QueryProposalsByGroupAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryProposalsByGroupAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposals", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposals = append(m.Proposals, &Proposal{}) + if err := m.Proposals[len(m.Proposals)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteByProposalVoterRequest) 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 ErrIntOverflowQuery + } + 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: QueryVoteByProposalVoterRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteByProposalVoterRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteByProposalVoterResponse) 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 ErrIntOverflowQuery + } + 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: QueryVoteByProposalVoterResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteByProposalVoterResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Vote == nil { + m.Vote = &Vote{} + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesByProposalRequest) 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 ErrIntOverflowQuery + } + 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: QueryVotesByProposalRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesByProposalRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesByProposalResponse) 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 ErrIntOverflowQuery + } + 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: QueryVotesByProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesByProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, &Vote{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesByVoterRequest) 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 ErrIntOverflowQuery + } + 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: QueryVotesByVoterRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesByVoterRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesByVoterResponse) 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 ErrIntOverflowQuery + } + 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: QueryVotesByVoterResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesByVoterResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, &Vote{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPollRequest) 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 ErrIntOverflowQuery + } + 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: QueryPollRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPollRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPollResponse) 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 ErrIntOverflowQuery + } + 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: QueryPollResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPollResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Poll", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Poll == nil { + m.Poll = &Poll{} + } + if err := m.Poll.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPollsByGroupRequest) 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 ErrIntOverflowQuery + } + 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: QueryPollsByGroupRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPollsByGroupRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPollsByGroupResponse) 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 ErrIntOverflowQuery + } + 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: QueryPollsByGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPollsByGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Polls", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Polls = append(m.Polls, &Poll{}) + if err := m.Polls[len(m.Polls)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPollsByCreatorRequest) 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 ErrIntOverflowQuery + } + 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: QueryPollsByCreatorRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPollsByCreatorRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPollsByCreatorResponse) 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 ErrIntOverflowQuery + } + 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: QueryPollsByCreatorResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPollsByCreatorResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Polls", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Polls = append(m.Polls, &Poll{}) + if err := m.Polls[len(m.Polls)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteForPollByPollVoterRequest) 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 ErrIntOverflowQuery + } + 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: QueryVoteForPollByPollVoterRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteForPollByPollVoterRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVoteForPollByPollVoterResponse) 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 ErrIntOverflowQuery + } + 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: QueryVoteForPollByPollVoterResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVoteForPollByPollVoterResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Vote == nil { + m.Vote = &VotePoll{} + } + if err := m.Vote.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesForPollByPollRequest) 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 ErrIntOverflowQuery + } + 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: QueryVotesForPollByPollRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesForPollByPollRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesForPollByPollResponse) 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 ErrIntOverflowQuery + } + 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: QueryVotesForPollByPollResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesForPollByPollResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, &VotePoll{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesForPollByVoterRequest) 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 ErrIntOverflowQuery + } + 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: QueryVotesForPollByVoterRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesForPollByVoterRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryVotesForPollByVoterResponse) 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 ErrIntOverflowQuery + } + 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: QueryVotesForPollByVoterResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryVotesForPollByVoterResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, &VotePoll{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/group/query.pb.gw.go b/x/group/query.pb.gw.go new file mode 100644 index 0000000000..ec070b66d1 --- /dev/null +++ b/x/group/query.pb.gw.go @@ -0,0 +1,2011 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: regen/group/v1alpha1/query.proto + +/* +Package group is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package group + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage +var _ = metadata.Join + +func request_Query_GroupInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + msg, err := client.GroupInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GroupInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + msg, err := server.GroupInfo(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_GroupAccountInfo_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupAccountInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := client.GroupAccountInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GroupAccountInfo_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupAccountInfoRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := server.GroupAccountInfo(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_GroupMembers_0 = &utilities.DoubleArray{Encoding: map[string]int{"group_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_GroupMembers_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupMembersRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupMembers_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GroupMembers(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GroupMembers_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupMembersRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupMembers_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GroupMembers(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_GroupsByAdmin_0 = &utilities.DoubleArray{Encoding: map[string]int{"admin": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_GroupsByAdmin_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupsByAdminRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["admin"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "admin") + } + + protoReq.Admin, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "admin", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupsByAdmin_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GroupsByAdmin(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GroupsByAdmin_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupsByAdminRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["admin"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "admin") + } + + protoReq.Admin, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "admin", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupsByAdmin_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GroupsByAdmin(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_GroupAccountsByGroup_0 = &utilities.DoubleArray{Encoding: map[string]int{"group_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_GroupAccountsByGroup_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupAccountsByGroupRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupAccountsByGroup_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GroupAccountsByGroup(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GroupAccountsByGroup_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupAccountsByGroupRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["group_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "group_id") + } + + protoReq.GroupId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "group_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupAccountsByGroup_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GroupAccountsByGroup(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_GroupAccountsByAdmin_0 = &utilities.DoubleArray{Encoding: map[string]int{"admin": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_GroupAccountsByAdmin_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupAccountsByAdminRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["admin"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "admin") + } + + protoReq.Admin, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "admin", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupAccountsByAdmin_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GroupAccountsByAdmin(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_GroupAccountsByAdmin_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryGroupAccountsByAdminRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["admin"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "admin") + } + + protoReq.Admin, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "admin", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_GroupAccountsByAdmin_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GroupAccountsByAdmin(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := client.Proposal(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Proposal_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + msg, err := server.Proposal(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_ProposalsByGroupAccount_0 = &utilities.DoubleArray{Encoding: map[string]int{"address": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_ProposalsByGroupAccount_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalsByGroupAccountRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ProposalsByGroupAccount_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ProposalsByGroupAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_ProposalsByGroupAccount_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryProposalsByGroupAccountRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_ProposalsByGroupAccount_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ProposalsByGroupAccount(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_VoteByProposalVoter_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteByProposalVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := client.VoteByProposalVoter(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VoteByProposalVoter_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteByProposalVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := server.VoteByProposalVoter(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_VotesByProposal_0 = &utilities.DoubleArray{Encoding: map[string]int{"proposal_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_VotesByProposal_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesByProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesByProposal_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.VotesByProposal(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VotesByProposal_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesByProposalRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["proposal_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "proposal_id") + } + + protoReq.ProposalId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "proposal_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesByProposal_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.VotesByProposal(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_VotesByVoter_0 = &utilities.DoubleArray{Encoding: map[string]int{"voter": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_VotesByVoter_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesByVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesByVoter_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.VotesByVoter(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VotesByVoter_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesByVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesByVoter_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.VotesByVoter(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_Poll_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPollRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["poll_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "poll_id") + } + + protoReq.PollId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "poll_id", err) + } + + msg, err := client.Poll(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Poll_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPollRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["poll_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "poll_id") + } + + protoReq.PollId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "poll_id", err) + } + + msg, err := server.Poll(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_PollsByGroup_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_Query_PollsByGroup_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPollsByGroupRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PollsByGroup_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.PollsByGroup(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_PollsByGroup_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPollsByGroupRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PollsByGroup_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.PollsByGroup(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_PollsByCreator_0 = &utilities.DoubleArray{Encoding: map[string]int{"creator": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_PollsByCreator_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPollsByCreatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["creator"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "creator") + } + + protoReq.Creator, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "creator", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PollsByCreator_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.PollsByCreator(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_PollsByCreator_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryPollsByCreatorRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["creator"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "creator") + } + + protoReq.Creator, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "creator", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_PollsByCreator_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.PollsByCreator(ctx, &protoReq) + return msg, metadata, err + +} + +func request_Query_VoteForPollByPollVoter_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteForPollByPollVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["poll_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "poll_id") + } + + protoReq.PollId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "poll_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := client.VoteForPollByPollVoter(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VoteForPollByPollVoter_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVoteForPollByPollVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["poll_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "poll_id") + } + + protoReq.PollId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "poll_id", err) + } + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + msg, err := server.VoteForPollByPollVoter(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_VotesForPollByPoll_0 = &utilities.DoubleArray{Encoding: map[string]int{"poll_id": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_VotesForPollByPoll_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesForPollByPollRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["poll_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "poll_id") + } + + protoReq.PollId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "poll_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesForPollByPoll_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.VotesForPollByPoll(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VotesForPollByPoll_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesForPollByPollRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["poll_id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "poll_id") + } + + protoReq.PollId, err = runtime.Uint64(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "poll_id", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesForPollByPoll_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.VotesForPollByPoll(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_Query_VotesForPollByVoter_0 = &utilities.DoubleArray{Encoding: map[string]int{"voter": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_Query_VotesForPollByVoter_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesForPollByVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesForPollByVoter_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.VotesForPollByVoter(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_VotesForPollByVoter_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QueryVotesForPollByVoterRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["voter"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "voter") + } + + protoReq.Voter, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "voter", err) + } + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_VotesForPollByVoter_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.VotesForPollByVoter(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_GroupInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GroupInfo_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupAccountInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GroupAccountInfo_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupAccountInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupMembers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GroupMembers_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupMembers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupsByAdmin_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GroupsByAdmin_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupsByAdmin_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupAccountsByGroup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GroupAccountsByGroup_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupAccountsByGroup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupAccountsByAdmin_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_GroupAccountsByAdmin_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupAccountsByAdmin_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Proposal_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Proposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ProposalsByGroupAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_ProposalsByGroupAccount_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ProposalsByGroupAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VoteByProposalVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VoteByProposalVoter_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteByProposalVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesByProposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VotesByProposal_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesByProposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesByVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VotesByVoter_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesByVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Poll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Poll_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Poll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PollsByGroup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PollsByGroup_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PollsByGroup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PollsByCreator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_PollsByCreator_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PollsByCreator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VoteForPollByPollVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VoteForPollByPollVoter_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteForPollByPollVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesForPollByPoll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VotesForPollByPoll_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesForPollByPoll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesForPollByVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_VotesForPollByVoter_0(rctx, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesForPollByVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_GroupInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GroupInfo_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupAccountInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GroupAccountInfo_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupAccountInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupMembers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GroupMembers_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupMembers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupsByAdmin_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GroupsByAdmin_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupsByAdmin_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupAccountsByGroup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GroupAccountsByGroup_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupAccountsByGroup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_GroupAccountsByAdmin_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_GroupAccountsByAdmin_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_GroupAccountsByAdmin_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Proposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Proposal_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Proposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_ProposalsByGroupAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_ProposalsByGroupAccount_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_ProposalsByGroupAccount_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VoteByProposalVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VoteByProposalVoter_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteByProposalVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesByProposal_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VotesByProposal_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesByProposal_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesByVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VotesByVoter_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesByVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_Poll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Poll_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Poll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PollsByGroup_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_PollsByGroup_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PollsByGroup_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_PollsByCreator_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_PollsByCreator_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_PollsByCreator_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VoteForPollByPollVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VoteForPollByPollVoter_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VoteForPollByPollVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesForPollByPoll_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VotesForPollByPoll_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesForPollByPoll_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_Query_VotesForPollByVoter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_VotesForPollByVoter_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_VotesForPollByVoter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_GroupInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "groups", "group_id", "info"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_GroupAccountInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"regen", "group", "v1alpha1", "groups", "accounts", "address"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_GroupMembers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "groups", "group_id", "members"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_GroupsByAdmin_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"regen", "group", "v1alpha1", "groups", "admins", "admin"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_GroupAccountsByGroup_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "groups", "group_id", "accounts"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_GroupAccountsByAdmin_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "admins", "admin", "accounts"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Proposal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"regen", "group", "v1alpha1", "proposals", "proposal_id"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_ProposalsByGroupAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "group-accounts", "address", "proposals"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VoteByProposalVoter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"regen", "group", "v1alpha1", "proposals", "proposal_id", "votes", "voter"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VotesByProposal_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "proposals", "proposal_id", "votes"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VotesByVoter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"regen", "group", "v1alpha1", "voters", "voter"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_Poll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"regen", "group", "v1alpha1", "polls", "poll_id"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_PollsByGroup_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 1, 2, 3}, []string{"regen", "group", "v1alpha1", "polls"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_PollsByCreator_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "creators", "creator", "polls"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VoteForPollByPollVoter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5, 1, 0, 4, 1, 5, 6}, []string{"regen", "group", "v1alpha1", "polls", "poll_id", "votes", "voter"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VotesForPollByPoll_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"regen", "group", "v1alpha1", "polls", "poll_id", "votes"}, "", runtime.AssumeColonVerbOpt(true))) + + pattern_Query_VotesForPollByVoter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"regen", "group", "v1alpha1", "voters", "voter"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_GroupInfo_0 = runtime.ForwardResponseMessage + + forward_Query_GroupAccountInfo_0 = runtime.ForwardResponseMessage + + forward_Query_GroupMembers_0 = runtime.ForwardResponseMessage + + forward_Query_GroupsByAdmin_0 = runtime.ForwardResponseMessage + + forward_Query_GroupAccountsByGroup_0 = runtime.ForwardResponseMessage + + forward_Query_GroupAccountsByAdmin_0 = runtime.ForwardResponseMessage + + forward_Query_Proposal_0 = runtime.ForwardResponseMessage + + forward_Query_ProposalsByGroupAccount_0 = runtime.ForwardResponseMessage + + forward_Query_VoteByProposalVoter_0 = runtime.ForwardResponseMessage + + forward_Query_VotesByProposal_0 = runtime.ForwardResponseMessage + + forward_Query_VotesByVoter_0 = runtime.ForwardResponseMessage + + forward_Query_Poll_0 = runtime.ForwardResponseMessage + + forward_Query_PollsByGroup_0 = runtime.ForwardResponseMessage + + forward_Query_PollsByCreator_0 = runtime.ForwardResponseMessage + + forward_Query_VoteForPollByPollVoter_0 = runtime.ForwardResponseMessage + + forward_Query_VotesForPollByPoll_0 = runtime.ForwardResponseMessage + + forward_Query_VotesForPollByVoter_0 = runtime.ForwardResponseMessage +) diff --git a/x/group/server/gas.go b/x/group/server/gas.go new file mode 100644 index 0000000000..ec6ce69798 --- /dev/null +++ b/x/group/server/gas.go @@ -0,0 +1,73 @@ +package server + +import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "math" +) + +func addUint64Overflow(a, b uint64) (uint64, bool) { + if math.MaxUint64-a < b { + return 0, true + } + + return a + b, false +} + +func mulUint64Overflow(a, b uint64) (uint64, bool) { + if math.MaxUint64/a < b { + return 0, true + } + return a*b, false +} + +func subUint64Overflow(a, b uint64) (uint64, bool) { + if a < b { + return 0, true + } + + return a - b, false +} + +// DefaultSigVerificationGasConsumer computes and consumes gas cost using the formula: +// gas := base + pairingCost * (numMsg - 1) + additionCost * (numPk - numMsg) +func DefaultAggSigVerifyGasConsumer(meter sdk.GasMeter, numPk uint64, numMsg uint64, params authtypes.Params) error { + base := params.SigVerifyCostBls12381 + pairingCost := base*33/10 + additionCost := base/1215 + + sub, overflow := subUint64Overflow(numMsg, 1) + if overflow { + return fmt.Errorf("subtraction between uint64 overflow") + } + + mul, overflow := mulUint64Overflow(pairingCost, sub) + if overflow { + return fmt.Errorf("multiplication between uint64 overflow") + } + + sub2, overflow := subUint64Overflow(numPk, numMsg) + if overflow { + return fmt.Errorf("subtraction between uint64 overflow") + } + + mul2, overflow := mulUint64Overflow(additionCost, sub2) + if overflow { + return fmt.Errorf("multiplication between uint64 overflow") + } + + sum, overflow := addUint64Overflow(base, mul) + if overflow { + return fmt.Errorf("addition between uint64 overflow") + } + + gas, overflow := addUint64Overflow(sum, mul2) + if overflow { + return fmt.Errorf("addition between uint64 overflow") + } + + meter.ConsumeGas(gas, "verify aggregated signature") + + return nil +} \ No newline at end of file diff --git a/x/group/server/genesis.go b/x/group/server/genesis.go new file mode 100644 index 0000000000..d244896a03 --- /dev/null +++ b/x/group/server/genesis.go @@ -0,0 +1,111 @@ +package server + +import ( + "encoding/json" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/errors" + abci "github.com/tendermint/tendermint/abci/types" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/types" + "github.com/cosmos/cosmos-sdk/x/group" +) + +func (s serverImpl) InitGenesis(ctx types.Context, cdc codec.Codec, data json.RawMessage) ([]abci.ValidatorUpdate, error) { + var genesisState group.GenesisState + cdc.MustUnmarshalJSON(data, &genesisState) + + if err := orm.ImportTableData(ctx, s.groupTable, genesisState.Groups, genesisState.GroupSeq); err != nil { + return nil, errors.Wrap(err, "groups") + } + + if err := orm.ImportTableData(ctx, s.groupMemberTable, genesisState.GroupMembers, 0); err != nil { + return nil, errors.Wrap(err, "group members") + } + + if err := orm.ImportTableData(ctx, s.groupAccountTable, genesisState.GroupAccounts, 0); err != nil { + return nil, errors.Wrap(err, "group accounts") + } + if err := s.groupAccountSeq.InitVal(ctx, genesisState.GroupAccountSeq); err != nil { + return nil, errors.Wrap(err, "group account seq") + } + + if err := orm.ImportTableData(ctx, s.proposalTable, genesisState.Proposals, genesisState.ProposalSeq); err != nil { + return nil, errors.Wrap(err, "proposals") + } + + if err := orm.ImportTableData(ctx, s.voteTable, genesisState.Votes, 0); err != nil { + return nil, errors.Wrap(err, "votes") + } + + if err := orm.ImportTableData(ctx, s.pollTable, genesisState.Polls, genesisState.PollSeq); err != nil { + return nil, errors.Wrap(err, "polls") + } + + if err := orm.ImportTableData(ctx, s.votePollTable, genesisState.VotesForPoll, 0); err != nil { + return nil, errors.Wrap(err, "votes") + } + + return []abci.ValidatorUpdate{}, nil +} + +func (s serverImpl) ExportGenesis(ctx types.Context, cdc codec.Codec) (json.RawMessage, error) { + genesisState := group.NewGenesisState() + + var groups []*group.GroupInfo + groupSeq, err := orm.ExportTableData(ctx, s.groupTable, &groups) + if err != nil { + return nil, errors.Wrap(err, "groups") + } + genesisState.Groups = groups + genesisState.GroupSeq = groupSeq + + var groupMembers []*group.GroupMember + _, err = orm.ExportTableData(ctx, s.groupMemberTable, &groupMembers) + if err != nil { + return nil, errors.Wrap(err, "group members") + } + genesisState.GroupMembers = groupMembers + + var groupAccounts []*group.GroupAccountInfo + _, err = orm.ExportTableData(ctx, s.groupAccountTable, &groupAccounts) + if err != nil { + return nil, errors.Wrap(err, "group accounts") + } + genesisState.GroupAccounts = groupAccounts + genesisState.GroupAccountSeq = s.groupAccountSeq.CurVal(ctx) + + var proposals []*group.Proposal + proposalSeq, err := orm.ExportTableData(ctx, s.proposalTable, &proposals) + if err != nil { + return nil, errors.Wrap(err, "proposals") + } + genesisState.Proposals = proposals + genesisState.ProposalSeq = proposalSeq + + var votes []*group.Vote + _, err = orm.ExportTableData(ctx, s.voteTable, &votes) + if err != nil { + return nil, errors.Wrap(err, "votes") + } + genesisState.Votes = votes + + var polls []*group.Poll + pollSeq, err := orm.ExportTableData(ctx, s.pollTable, &polls) + if err != nil { + return nil, errors.Wrap(err, "polls") + } + genesisState.Polls = polls + genesisState.PollSeq = pollSeq + + var votesForPoll []*group.VotePoll + _, err = orm.ExportTableData(ctx, s.votePollTable, &votesForPoll) + if err != nil { + return nil, errors.Wrap(err, "votes for poll") + } + genesisState.VotesForPoll = votesForPoll + + genesisBytes := cdc.MustMarshalJSON(genesisState) + return genesisBytes, nil +} diff --git a/x/group/server/invariants.go b/x/group/server/invariants.go new file mode 100644 index 0000000000..cceaf596bb --- /dev/null +++ b/x/group/server/invariants.go @@ -0,0 +1,352 @@ +package server + +import ( + "fmt" + "math" + + "github.com/cockroachdb/apd/v2" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/cosmos-sdk/regen/orm" + regenMath "github.com/cosmos/cosmos-sdk/regen/types/math" + "github.com/cosmos/cosmos-sdk/x/group" +) + +const ( + votesInvariant = "Tally-Votes" + weightInvariant = "Group-TotalWeight" + votesSumInvariant = "Tally-Votes-Sum" +) + +func (s serverImpl) RegisterInvariants(ir sdk.InvariantRegistry) { + ir.RegisterRoute(group.ModuleName, votesInvariant, s.tallyVotesInvariant()) + ir.RegisterRoute(group.ModuleName, weightInvariant, s.groupTotalWeightInvariant()) + ir.RegisterRoute(group.ModuleName, votesSumInvariant, s.tallyVotesSumInvariant()) +} + +func (s serverImpl) tallyVotesInvariant() sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + if ctx.BlockHeight()-1 < 0 { + return sdk.FormatInvariant(group.ModuleName, votesInvariant, "Not enough blocks to perform TallyVotesInvariant"), false + } + prevCtx, _ := ctx.CacheContext() + prevCtx = prevCtx.WithBlockHeight(ctx.BlockHeight() - 1) + msg, broken := tallyVotesInvariant(ctx, prevCtx, s.proposalTable) + return sdk.FormatInvariant(group.ModuleName, votesInvariant, msg), broken + } +} + +func (s serverImpl) groupTotalWeightInvariant() sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + msg, broken := groupTotalWeightInvariant(ctx, s.groupTable, s.groupMemberByGroupIndex) + return sdk.FormatInvariant(group.ModuleName, weightInvariant, msg), broken + } +} + +func (s serverImpl) tallyVotesSumInvariant() sdk.Invariant { + return func(ctx sdk.Context) (string, bool) { + msg, broken := tallyVotesSumInvariant(ctx, s.groupTable, s.proposalTable, s.groupMemberTable, s.voteByProposalIndex, s.groupAccountTable) + return sdk.FormatInvariant(group.ModuleName, votesSumInvariant, msg), broken + } +} + +func tallyVotesInvariant(ctx sdk.Context, prevCtx sdk.Context, proposalTable orm.AutoUInt64Table) (string, bool) { + + var msg string + var broken bool + + prevIt, err := proposalTable.PrefixScan(prevCtx, 1, math.MaxUint64) + if err != nil { + msg += fmt.Sprintf("PrefixScan failure on proposal table at block height %d\n%v\n", prevCtx.BlockHeight(), err) + return msg, broken + } + + curIt, err := proposalTable.PrefixScan(ctx, 1, math.MaxUint64) + if err != nil { + msg += fmt.Sprintf("PrefixScan failure on proposal table at block height %d\n%v\n", ctx.BlockHeight(), err) + return msg, broken + } + + var curProposals []*group.Proposal + _, err = orm.ReadAll(curIt, &curProposals) + if err != nil { + msg += fmt.Sprintf("error while getting all the proposals at block height %d\n%v\n", ctx.BlockHeight(), err) + return msg, broken + } + + var prevProposals []*group.Proposal + _, err = orm.ReadAll(prevIt, &prevProposals) + if err != nil { + msg += fmt.Sprintf("error while getting all the proposals at block height %d\n%v\n", prevCtx.BlockHeight(), err) + return msg, broken + } + + for i := 0; i < len(prevProposals); i++ { + if prevProposals[i].ProposalId == curProposals[i].ProposalId { + prevYesCount, err := prevProposals[i].VoteState.GetYesCount() + if err != nil { + msg += fmt.Sprintf("error while getting yes votes weight of proposal at block height %d\n%v\n", prevCtx.BlockHeight(), err) + return msg, broken + } + curYesCount, err := curProposals[i].VoteState.GetYesCount() + if err != nil { + msg += fmt.Sprintf("error while getting yes votes weight of proposal at block height %d\n%v\n", ctx.BlockHeight(), err) + return msg, broken + } + prevNoCount, err := prevProposals[i].VoteState.GetNoCount() + if err != nil { + msg += fmt.Sprintf("error while getting no votes weight of proposal at block height %d\n%v\n", prevCtx.BlockHeight(), err) + return msg, broken + } + curNoCount, err := curProposals[i].VoteState.GetNoCount() + if err != nil { + msg += fmt.Sprintf("error while getting no votes weight of proposal at block height %d\n%v\n", ctx.BlockHeight(), err) + return msg, broken + } + prevAbstainCount, err := prevProposals[i].VoteState.GetAbstainCount() + if err != nil { + msg += fmt.Sprintf("error while getting abstain votes weight of proposal at block height %d\n%v\n", prevCtx.BlockHeight(), err) + return msg, broken + } + curAbstainCount, err := curProposals[i].VoteState.GetAbstainCount() + if err != nil { + msg += fmt.Sprintf("error while getting abstain votes weight of proposal at block height %d\n%v\n", ctx.BlockHeight(), err) + return msg, broken + } + prevVetoCount, err := prevProposals[i].VoteState.GetVetoCount() + if err != nil { + msg += fmt.Sprintf("error while getting veto votes weight of proposal at block height %d\n%v\n", prevCtx.BlockHeight(), err) + return msg, broken + } + curVetoCount, err := curProposals[i].VoteState.GetVetoCount() + if err != nil { + msg += fmt.Sprintf("error while getting veto votes weight of proposal at block height %d\n%v\n", ctx.BlockHeight(), err) + return msg, broken + } + if (curYesCount.Cmp(prevYesCount) == -1) || (curNoCount.Cmp(prevNoCount) == -1) || (curAbstainCount.Cmp(prevAbstainCount) == -1) || (curVetoCount.Cmp(prevVetoCount) == -1) { + broken = true + msg += "vote tally sums must never have less than the block before\n" + return msg, broken + } + } + } + return msg, broken +} + +func groupTotalWeightInvariant(ctx sdk.Context, groupTable orm.AutoUInt64Table, groupMemberByGroupIndex orm.UInt64Index) (string, bool) { + + var msg string + var broken bool + + var groupInfo group.GroupInfo + var groupMember group.GroupMember + + groupIt, err := groupTable.PrefixScan(ctx, 1, math.MaxUint64) + if err != nil { + msg += fmt.Sprintf("PrefixScan failure on group table\n%v\n", err) + return msg, broken + } + defer groupIt.Close() + + for { + membersWeight := apd.New(0, 0) + _, err := groupIt.LoadNext(&groupInfo) + if orm.ErrIteratorDone.Is(err) { + break + } + memIt, err := groupMemberByGroupIndex.Get(ctx, groupInfo.GroupId) + if err != nil { + msg += fmt.Sprintf("error while returning group member iterator for group with ID %d\n%v\n", groupInfo.GroupId, err) + return msg, broken + } + defer memIt.Close() + + for { + _, err = memIt.LoadNext(&groupMember) + if orm.ErrIteratorDone.Is(err) { + break + } + curMemWeight, err := regenMath.ParseNonNegativeDecimal(groupMember.GetMember().GetWeight()) + if err != nil { + msg += fmt.Sprintf("error while parsing non-nengative decimal for group member %s\n%v\n", groupMember.Member.Address, err) + return msg, broken + } + err = regenMath.Add(membersWeight, membersWeight, curMemWeight) + if err != nil { + msg += fmt.Sprintf("decimal addition error while adding group member voting weight to total voting weight\n%v\n", err) + return msg, broken + } + } + groupWeight, err := regenMath.ParseNonNegativeDecimal(groupInfo.GetTotalWeight()) + if err != nil { + msg += fmt.Sprintf("error while parsing non-nengative decimal for group with ID %d\n%v\n", groupInfo.GroupId, err) + return msg, broken + } + + if groupWeight.Cmp(membersWeight) != 0 { + broken = true + msg += fmt.Sprintf("group's TotalWeight must be equal to the sum of its members' weights\ngroup weight: %s\nSum of group members weights: %s\n", groupWeight.String(), membersWeight.String()) + break + } + } + return msg, broken +} + +func tallyVotesSumInvariant(ctx sdk.Context, groupTable orm.AutoUInt64Table, proposalTable orm.AutoUInt64Table, groupMemberTable orm.PrimaryKeyTable, voteByProposalIndex orm.UInt64Index, groupAccountTable orm.PrimaryKeyTable) (string, bool) { + var msg string + var broken bool + + var groupInfo group.GroupInfo + var proposal group.Proposal + var groupAcc group.GroupAccountInfo + var groupMem group.GroupMember + var vote group.Vote + + proposalIt, err := proposalTable.PrefixScan(ctx, 1, math.MaxUint64) + if err != nil { + msg += fmt.Sprintf("PrefixScan failure on proposal table\n%v\n", err) + return msg, broken + } + defer proposalIt.Close() + + for { + + totalVotingWeight := apd.New(0, 0) + yesVoteWeight := apd.New(0, 0) + noVoteWeight := apd.New(0, 0) + abstainVoteWeight := apd.New(0, 0) + vetoVoteWeight := apd.New(0, 0) + + _, err := proposalIt.LoadNext(&proposal) + if orm.ErrIteratorDone.Is(err) { + break + } + + address, err := sdk.AccAddressFromBech32(proposal.Address) + if err != nil { + msg += fmt.Sprintf("error while converting proposal address of type string to type AccAddress\n%v\n", err) + return msg, broken + } + + err = groupAccountTable.GetOne(ctx, orm.AddLengthPrefix(address.Bytes()), &groupAcc) + if err != nil { + msg += fmt.Sprintf("group account not found for address: %s\n%v\n", proposal.Address, err) + return msg, broken + } + + if proposal.GroupAccountVersion != groupAcc.Version { + msg += fmt.Sprintf("group account with address %s was modified\n", groupAcc.Address) + return msg, broken + } + + _, err = groupTable.GetOne(ctx, groupAcc.GroupId, &groupInfo) + if err != nil { + msg += fmt.Sprintf("group info not found for group id %d\n%v\n", groupAcc.GroupId, err) + return msg, broken + } + + if groupInfo.Version != proposal.GroupVersion { + msg += fmt.Sprintf("group with id %d was modified\n", groupInfo.GroupId) + return msg, broken + } + + voteIt, err := voteByProposalIndex.Get(ctx, proposal.ProposalId) + if err != nil { + msg += fmt.Sprintf("error while returning vote iterator for proposal with ID %d\n%v\n", proposal.ProposalId, err) + return msg, broken + } + defer voteIt.Close() + + for { + _, err := voteIt.LoadNext(&vote) + if orm.ErrIteratorDone.Is(err) { + break + } + + groupMem = group.GroupMember{GroupId: groupAcc.GroupId, Member: &group.Member{Address: vote.Voter}} + + err = groupMemberTable.GetOne(ctx, orm.PrimaryKey(&groupMem), &groupMem) + if err != nil { + msg += fmt.Sprintf("group member not found with group ID %d and group member %s\n%v\n", groupAcc.GroupId, vote.Voter, err) + return msg, broken + } + + curMemVotingWeight, err := regenMath.ParseNonNegativeDecimal(groupMem.Member.Weight) + if err != nil { + msg += fmt.Sprintf("error while parsing non-negative decimal for group member %s\n%v\n", groupMem.Member.Address, err) + return msg, broken + } + err = regenMath.Add(totalVotingWeight, totalVotingWeight, curMemVotingWeight) + if err != nil { + msg += fmt.Sprintf("decimal addition error while adding current member voting weight to total voting weight\n%v\n", err) + return msg, broken + } + + switch vote.Choice { + case group.Choice_CHOICE_YES: + err = regenMath.Add(yesVoteWeight, yesVoteWeight, curMemVotingWeight) + if err != nil { + msg += fmt.Sprintf("decimal addition error\n%v\n", err) + return msg, broken + } + case group.Choice_CHOICE_NO: + err = regenMath.Add(noVoteWeight, noVoteWeight, curMemVotingWeight) + if err != nil { + msg += fmt.Sprintf("decimal addition error\n%v\n", err) + return msg, broken + } + case group.Choice_CHOICE_ABSTAIN: + err = regenMath.Add(abstainVoteWeight, abstainVoteWeight, curMemVotingWeight) + if err != nil { + msg += fmt.Sprintf("decimal addition error\n%v\n", err) + return msg, broken + } + case group.Choice_CHOICE_VETO: + err = regenMath.Add(vetoVoteWeight, vetoVoteWeight, curMemVotingWeight) + if err != nil { + msg += fmt.Sprintf("decimal addition error\n%v\n", err) + return msg, broken + } + } + } + + totalProposalVotes, err := proposal.VoteState.TotalCounts() + if err != nil { + msg += fmt.Sprintf("error while getting total weighted votes of proposal with ID %d\n%v\n", proposal.ProposalId, err) + return msg, broken + } + proposalYesCount, err := proposal.VoteState.GetYesCount() + if err != nil { + msg += fmt.Sprintf("error while getting the weighted sum of yes votes for proposal with ID %d\n%v\n", proposal.ProposalId, err) + return msg, broken + } + proposalNoCount, err := proposal.VoteState.GetNoCount() + if err != nil { + msg += fmt.Sprintf("error while getting the weighted sum of no votes for proposal with ID %d\n%v\n", proposal.ProposalId, err) + return msg, broken + } + proposalAbstainCount, err := proposal.VoteState.GetAbstainCount() + if err != nil { + msg += fmt.Sprintf("error while getting the weighted sum of abstain votes for proposal with ID %d\n%v\n", proposal.ProposalId, err) + return msg, broken + } + proposalVetoCount, err := proposal.VoteState.GetVetoCount() + if err != nil { + msg += fmt.Sprintf("error while getting the weighted sum of veto votes for proposal with ID %d\n%v\n", proposal.ProposalId, err) + return msg, broken + } + + if totalProposalVotes.Cmp(totalVotingWeight) != 0 { + broken = true + msg += fmt.Sprintf("proposal VoteState must correspond to the sum of votes weights\nProposal with ID %d has total proposal votes %s, but got sum of votes weights %s\n", proposal.ProposalId, totalProposalVotes.String(), totalVotingWeight.String()) + break + } + + if (yesVoteWeight.Cmp(proposalYesCount) != 0) || (noVoteWeight.Cmp(proposalNoCount) != 0) || (abstainVoteWeight.Cmp(proposalAbstainCount) != 0) || (vetoVoteWeight.Cmp(proposalVetoCount) != 0) { + broken = true + msg += fmt.Sprintf("proposal VoteState must correspond to the vote choice\nProposal with ID %d and voter address %s must correspond to the vote choice\n", proposal.ProposalId, vote.Voter) + break + } + } + return msg, broken +} diff --git a/x/group/server/invariants_test.go b/x/group/server/invariants_test.go new file mode 100644 index 0000000000..832ae38ff0 --- /dev/null +++ b/x/group/server/invariants_test.go @@ -0,0 +1,582 @@ +package server + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/store" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + gogotypes "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/require" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + dbm "github.com/tendermint/tm-db" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/x/group" +) + +func getCtxCodecKey(t *testing.T) (sdk.Context, *codec.ProtoCodec, *sdk.KVStoreKey) { + interfaceRegistry := types.NewInterfaceRegistry() + group.RegisterTypes(interfaceRegistry) + cdc := codec.NewProtoCodec(interfaceRegistry) + key := sdk.NewKVStoreKey(group.ModuleName) + db := dbm.NewMemDB() + cms := store.NewCommitMultiStore(db) + cms.MountStoreWithDB(key, sdk.StoreTypeIAVL, db) + err := cms.LoadLatestVersion() + require.NoError(t, err) + curCtx := sdk.NewContext(cms, tmproto.Header{}, false, log.NewNopLogger()) + curCtx = curCtx.WithBlockHeight(10) + return curCtx, cdc, key +} + +func TestTallyVotesInvariant(t *testing.T) { + curCtx, cdc, key := getCtxCodecKey(t) + prevCtx, _ := curCtx.CacheContext() + prevCtx = prevCtx.WithBlockHeight(curCtx.BlockHeight() - 1) + + // Proposal Table + proposalTableBuilder := orm.NewAutoUInt64TableBuilder(ProposalTablePrefix, ProposalTableSeqPrefix, key, &group.Proposal{}, cdc) + proposalTable := proposalTableBuilder.Build() + + _, _, addr1 := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + curBlockTime, err := gogotypes.TimestampProto(curCtx.BlockTime()) + require.NoError(t, err) + prevBlockTime, err := gogotypes.TimestampProto(prevCtx.BlockTime()) + require.NoError(t, err) + + specs := map[string]struct { + prevProposal *group.Proposal + curProposal *group.Proposal + expBroken bool + }{ + "invariant not broken": { + prevProposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *prevBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "1", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + + curProposal: &group.Proposal{ + ProposalId: 1, + Address: addr2.String(), + Proposers: []string{addr2.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "2", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + }, + "current block yes vote count must be greater than previous block yes vote count": { + prevProposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *prevBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "2", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + curProposal: &group.Proposal{ + ProposalId: 1, + Address: addr2.String(), + Proposers: []string{addr2.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "1", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + expBroken: true, + }, + "current block no vote count must be greater than previous block no vote count": { + prevProposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *prevBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "0", NoCount: "2", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + curProposal: &group.Proposal{ + ProposalId: 1, + Address: addr2.String(), + Proposers: []string{addr2.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "0", NoCount: "1", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + expBroken: true, + }, + "current block abstain vote count must be greater than previous block abstain vote count": { + prevProposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *prevBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "0", NoCount: "0", AbstainCount: "2", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + curProposal: &group.Proposal{ + ProposalId: 1, + Address: addr2.String(), + Proposers: []string{addr2.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "0", NoCount: "0", AbstainCount: "1", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + expBroken: true, + }, + "current block veto vote count must be greater than previous block veto vote count": { + prevProposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *prevBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "0", NoCount: "0", AbstainCount: "0", VetoCount: "2"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + curProposal: &group.Proposal{ + ProposalId: 1, + Address: addr2.String(), + Proposers: []string{addr2.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "0", NoCount: "0", AbstainCount: "0", VetoCount: "1"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + expBroken: true, + }, + } + + for _, spec := range specs { + + prevProposal := spec.prevProposal + curProposal := spec.curProposal + + cachePrevCtx, _ := prevCtx.CacheContext() + cacheCurCtx, _ := curCtx.CacheContext() + + _, err = proposalTable.Create(cachePrevCtx, prevProposal) + require.NoError(t, err) + _, err = proposalTable.Create(cacheCurCtx, curProposal) + require.NoError(t, err) + + _, broken := tallyVotesInvariant(cacheCurCtx, cachePrevCtx, proposalTable) + require.Equal(t, spec.expBroken, broken) + } +} + +func TestGroupTotalWeightInvariant(t *testing.T) { + curCtx, cdc, key := getCtxCodecKey(t) + + _, _, addr1 := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + // Group Table + groupTableBuilder := orm.NewAutoUInt64TableBuilder(GroupTablePrefix, GroupTableSeqPrefix, key, &group.GroupInfo{}, cdc) + groupTable := groupTableBuilder.Build() + + groupInfo := &group.GroupInfo{ + GroupId: 1, + Admin: addr1.String(), + Version: 1, + TotalWeight: "3", + } + rowID, err := groupTable.Create(curCtx, groupInfo) + require.NoError(t, err) + require.Equal(t, uint64(1), rowID) + + // Group Member Table + groupMemberTableBuilder := orm.NewPrimaryKeyTableBuilder(GroupMemberTablePrefix, key, &group.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + groupMemberByGroupIndex := orm.NewUInt64Index(groupMemberTableBuilder, GroupMemberByGroupIndexPrefix, func(val interface{}) ([]uint64, error) { + group := val.(*group.GroupMember).GroupId + return []uint64{group}, nil + }) + groupMemberTable := groupMemberTableBuilder.Build() + + specs := map[string]struct { + groupMembers []*group.GroupMember + expBroken bool + }{ + "invariant not broken": { + groupMembers: []*group.GroupMember{ + { + GroupId: 1, + Member: &group.Member{ + Address: addr1.String(), + Weight: "1", + }, + }, + { + GroupId: 1, + Member: &group.Member{ + Address: addr2.String(), + Weight: "2", + }, + }, + }, + expBroken: false, + }, + + "group's TotalWeight must be equal to sum of its members weight ": { + groupMembers: []*group.GroupMember{ + { + GroupId: 1, + Member: &group.Member{ + Address: addr1.String(), + Weight: "2", + }, + }, + { + GroupId: 1, + Member: &group.Member{ + Address: addr2.String(), + Weight: "2", + }, + }, + }, + expBroken: true, + }, + } + + for _, spec := range specs { + cacheCurCtx, _ := curCtx.CacheContext() + groupMembers := spec.groupMembers + + for i := 0; i < len(groupMembers); i++ { + err := groupMemberTable.Create(cacheCurCtx, groupMembers[i]) + require.NoError(t, err) + } + + _, broken := groupTotalWeightInvariant(cacheCurCtx, groupTable, groupMemberByGroupIndex) + require.Equal(t, spec.expBroken, broken) + } +} + +func TestTallyVotesSumInvariant(t *testing.T) { + curCtx, cdc, key := getCtxCodecKey(t) + + // Group Table + groupTableBuilder := orm.NewAutoUInt64TableBuilder(GroupTablePrefix, GroupTableSeqPrefix, key, &group.GroupInfo{}, cdc) + groupTable := groupTableBuilder.Build() + + // Group Account Table + groupAccountTableBuilder := orm.NewPrimaryKeyTableBuilder(GroupAccountTablePrefix, key, &group.GroupAccountInfo{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + groupAccountTable := groupAccountTableBuilder.Build() + + // Group Member Table + groupMemberTableBuilder := orm.NewPrimaryKeyTableBuilder(GroupMemberTablePrefix, key, &group.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + groupMemberTable := groupMemberTableBuilder.Build() + + // Proposal Table + proposalTableBuilder := orm.NewAutoUInt64TableBuilder(ProposalTablePrefix, ProposalTableSeqPrefix, key, &group.Proposal{}, cdc) + proposalTable := proposalTableBuilder.Build() + + // Vote Table + voteTableBuilder := orm.NewPrimaryKeyTableBuilder(VoteTablePrefix, key, &group.Vote{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + voteByProposalIndex := orm.NewUInt64Index(voteTableBuilder, VoteByProposalIndexPrefix, func(value interface{}) ([]uint64, error) { + return []uint64{value.(*group.Vote).ProposalId}, nil + }) + voteTable := voteTableBuilder.Build() + + _, _, adminAddr := testdata.KeyTestPubAddr() + _, _, addr1 := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + + curBlockTime, err := gogotypes.TimestampProto(curCtx.BlockTime()) + require.NoError(t, err) + + specs := map[string]struct { + groupsInfo *group.GroupInfo + groupAcc *group.GroupAccountInfo + groupMembers []*group.GroupMember + proposal *group.Proposal + votes []*group.Vote + expBroken bool + }{ + "invariant not broken": { + groupsInfo: &group.GroupInfo{ + GroupId: 1, + Admin: adminAddr.String(), + Version: 1, + TotalWeight: "7", + }, + groupAcc: &group.GroupAccountInfo{ + Address: addr1.String(), + GroupId: 1, + Admin: adminAddr.String(), + Version: 1, + DerivationKey: []byte("derivation-key"), + }, + groupMembers: []*group.GroupMember{ + { + GroupId: 1, + Member: &group.Member{ + Address: addr1.String(), + Weight: "4", + }, + }, + { + GroupId: 1, + Member: &group.Member{ + Address: addr2.String(), + Weight: "3", + }, + }, + }, + proposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "4", NoCount: "3", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + votes: []*group.Vote{ + { + ProposalId: 1, + Voter: addr1.String(), + Choice: group.Choice_CHOICE_YES, + SubmittedAt: gogotypes.Timestamp{ + Seconds: timestamppb.Now().Seconds, + Nanos: timestamppb.Now().Nanos, + }, + }, + { + ProposalId: 1, + Voter: addr2.String(), + Choice: group.Choice_CHOICE_NO, + SubmittedAt: gogotypes.Timestamp{ + Seconds: timestamppb.Now().Seconds, + Nanos: timestamppb.Now().Nanos, + }, + }, + }, + expBroken: false, + }, + "proposal tally must correspond to the sum of vote weights": { + groupsInfo: &group.GroupInfo{ + GroupId: 1, + Admin: adminAddr.String(), + Version: 1, + TotalWeight: "5", + }, + groupAcc: &group.GroupAccountInfo{ + Address: addr1.String(), + GroupId: 1, + Admin: adminAddr.String(), + Version: 1, + DerivationKey: []byte("derivation-key"), + }, + groupMembers: []*group.GroupMember{ + { + GroupId: 1, + Member: &group.Member{ + Address: addr1.String(), + Weight: "2", + }, + }, + { + GroupId: 1, + Member: &group.Member{ + Address: addr2.String(), + Weight: "3", + }, + }, + }, + proposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "6", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + votes: []*group.Vote{ + { + ProposalId: 1, + Voter: addr1.String(), + Choice: group.Choice_CHOICE_YES, + SubmittedAt: gogotypes.Timestamp{ + Seconds: timestamppb.Now().Seconds, + Nanos: timestamppb.Now().Nanos, + }, + }, + { + ProposalId: 1, + Voter: addr2.String(), + Choice: group.Choice_CHOICE_YES, + SubmittedAt: gogotypes.Timestamp{ + Seconds: timestamppb.Now().Seconds, + Nanos: timestamppb.Now().Nanos, + }, + }, + }, + expBroken: true, + }, + "proposal VoteState must correspond to the vote choice": { + groupsInfo: &group.GroupInfo{ + GroupId: 1, + Admin: adminAddr.String(), + Version: 1, + TotalWeight: "7", + }, + groupAcc: &group.GroupAccountInfo{ + Address: addr1.String(), + GroupId: 1, + Admin: adminAddr.String(), + Version: 1, + DerivationKey: []byte("derivation-key"), + }, + groupMembers: []*group.GroupMember{ + { + GroupId: 1, + Member: &group.Member{ + Address: addr1.String(), + Weight: "4", + }, + }, + { + GroupId: 1, + Member: &group.Member{ + Address: addr2.String(), + Weight: "3", + }, + }, + }, + proposal: &group.Proposal{ + ProposalId: 1, + Address: addr1.String(), + Proposers: []string{addr1.String()}, + SubmittedAt: *curBlockTime, + GroupVersion: 1, + GroupAccountVersion: 1, + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{YesCount: "4", NoCount: "3", AbstainCount: "0", VetoCount: "0"}, + Timeout: gogotypes.Timestamp{Seconds: 600}, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + votes: []*group.Vote{ + { + ProposalId: 1, + Voter: addr1.String(), + Choice: group.Choice_CHOICE_YES, + SubmittedAt: gogotypes.Timestamp{ + Seconds: timestamppb.Now().Seconds, + Nanos: timestamppb.Now().Nanos, + }, + }, + { + ProposalId: 1, + Voter: addr2.String(), + Choice: group.Choice_CHOICE_ABSTAIN, + SubmittedAt: gogotypes.Timestamp{ + Seconds: timestamppb.Now().Seconds, + Nanos: timestamppb.Now().Nanos, + }, + }, + }, + expBroken: true, + }, + } + + for _, spec := range specs { + cacheCurCtx, _ := curCtx.CacheContext() + groupsInfo := spec.groupsInfo + proposal := spec.proposal + groupAcc := spec.groupAcc + groupMembers := spec.groupMembers + votes := spec.votes + + groupID, err := groupTable.Create(cacheCurCtx, groupsInfo) + require.NoError(t, err) + require.Equal(t, groupsInfo.GroupId, groupID) + + err = groupAcc.SetDecisionPolicy(group.NewThresholdDecisionPolicy("1", gogotypes.Duration{Seconds: 1})) + require.NoError(t, err) + err = groupAccountTable.Create(cacheCurCtx, groupAcc) + require.NoError(t, err) + + for i := 0; i < len(groupMembers); i++ { + err = groupMemberTable.Create(cacheCurCtx, groupMembers[i]) + require.NoError(t, err) + } + + _, err = proposalTable.Create(cacheCurCtx, proposal) + require.NoError(t, err) + + for i := 0; i < len(votes); i++ { + err = voteTable.Create(cacheCurCtx, votes[i]) + require.NoError(t, err) + } + + _, broken := tallyVotesSumInvariant(cacheCurCtx, groupTable, proposalTable, groupMemberTable, voteByProposalIndex, groupAccountTable) + require.Equal(t, spec.expBroken, broken) + } +} diff --git a/x/group/server/msg_server.go b/x/group/server/msg_server.go new file mode 100644 index 0000000000..23599daa00 --- /dev/null +++ b/x/group/server/msg_server.go @@ -0,0 +1,1320 @@ +package server + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + "reflect" + + "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/cockroachdb/apd/v2" + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/types" + "github.com/cosmos/cosmos-sdk/regen/types/math" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/x/group" + gogotypes "github.com/gogo/protobuf/types" +) + +func (s serverImpl) validateBlsMember(ctx types.Context, mem group.Member) error { + addr, err := sdk.AccAddressFromBech32(mem.Address) + if err != nil { + return err + } + acc := s.accKeeper.GetAccount(ctx.Context, addr) + if acc == nil { + return fmt.Errorf("account %s does not exist", mem.Address) + } + + pk := acc.GetPubKey() + if pk == nil { + return fmt.Errorf("account public key not set yet") + } + + if _, ok := pk.(*bls12381.PubKey); !ok { + return fmt.Errorf("member account %s is not a bls account", mem.Address) + } + + if !acc.GetPopValid() { + return fmt.Errorf("member account %s hasn't validated pop for public key", mem.Address) + } + + return nil +} + +// TODO: Revisit this once we have propoer gas fee framework. +// Tracking issues https://github.com/cosmos/cosmos-sdk/issues/9054, https://github.com/cosmos/cosmos-sdk/discussions/9072 +const gasCostPerIteration = uint64(20) + +func (s serverImpl) CreateGroup(goCtx context.Context, req *group.MsgCreateGroup) (*group.MsgCreateGroupResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + metadata := req.Metadata + members := group.Members{Members: req.Members} + admin := req.Admin + bls := req.BlsOnly + + if err := members.ValidateBasic(); err != nil { + return nil, err + } + + if bls { + for _, mem := range members.Members { + if err := s.validateBlsMember(ctx, mem); err != nil { + return nil, sdkerrors.Wrapf(err, "member %s failed bls validation", mem.Address) + } + } + } + + totalWeight := apd.New(0, 0) + for i := range members.Members { + m := members.Members[i] + + // Members of a group must have a positive weight. + weight, err := math.ParsePositiveDecimal(m.Weight) + if err != nil { + return nil, err + } + + // Adding up members weights to compute group total weight. + err = math.Add(totalWeight, totalWeight, weight) + if err != nil { + return nil, err + } + } + + // Create a new group in the groupTable. + groupInfo := &group.GroupInfo{ + GroupId: s.groupTable.Sequence().PeekNextVal(ctx), + Admin: admin, + Metadata: metadata, + Version: 1, + TotalWeight: math.DecimalString(totalWeight), + BlsOnly: bls, + } + groupID, err := s.groupTable.Create(ctx, groupInfo) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not create group") + } + + // Create new group members in the groupMemberTable. + for i := range members.Members { + m := members.Members[i] + err := s.groupMemberTable.Create(ctx, &group.GroupMember{ + GroupId: groupID, + Member: &group.Member{ + Address: m.Address, + Weight: m.Weight, + Metadata: m.Metadata, + }, + }) + if err != nil { + return nil, sdkerrors.Wrapf(err, "could not store member %d", i) + } + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventCreateGroup{GroupId: groupID}) + if err != nil { + return nil, err + } + + return &group.MsgCreateGroupResponse{GroupId: groupID}, nil +} + +func (s serverImpl) UpdateGroupMembers(goCtx context.Context, req *group.MsgUpdateGroupMembers) (*group.MsgUpdateGroupMembersResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + action := func(g *group.GroupInfo) error { + totalWeight, err := math.ParseNonNegativeDecimal(g.TotalWeight) + if err != nil { + return err + } + + if g.BlsOnly { + for _, mem := range req.MemberUpdates { + if err := s.validateBlsMember(ctx, mem); err != nil { + return err + } + } + } + + for i := range req.MemberUpdates { + groupMember := group.GroupMember{GroupId: req.GroupId, + Member: &group.Member{ + Address: req.MemberUpdates[i].Address, + Weight: req.MemberUpdates[i].Weight, + Metadata: req.MemberUpdates[i].Metadata, + }, + } + + // Checking if the group member is already part of the group. + var found bool + var prevGroupMember group.GroupMember + switch err := s.groupMemberTable.GetOne(ctx, orm.PrimaryKey(&groupMember), &prevGroupMember); { + case err == nil: + found = true + case orm.ErrNotFound.Is(err): + found = false + default: + return sdkerrors.Wrap(err, "get group member") + } + + newMemberWeight, err := math.ParseNonNegativeDecimal(groupMember.Member.Weight) + if err != nil { + return err + } + + // Handle delete for members with zero weight. + if newMemberWeight.IsZero() { + // We can't delete a group member that doesn't already exist. + if !found { + return sdkerrors.Wrap(orm.ErrNotFound, "unknown member") + } + + previousMemberWeight, err := math.ParseNonNegativeDecimal(prevGroupMember.Member.Weight) + if err != nil { + return err + } + + // Subtract the weight of the group member to delete from the group total weight. + err = math.SafeSub(totalWeight, totalWeight, previousMemberWeight) + if err != nil { + return err + } + + // Delete group member in the groupMemberTable. + if err := s.groupMemberTable.Delete(ctx, &groupMember); err != nil { + return sdkerrors.Wrap(err, "delete member") + } + continue + } + // If group member already exists, handle update + if found { + previousMemberWeight, err := math.ParseNonNegativeDecimal(prevGroupMember.Member.Weight) + if err != nil { + return err + } + // Subtract previous weight from the group total weight. + err = math.SafeSub(totalWeight, totalWeight, previousMemberWeight) + if err != nil { + return err + } + // Save updated group member in the groupMemberTable. + if err := s.groupMemberTable.Save(ctx, &groupMember); err != nil { + return sdkerrors.Wrap(err, "add member") + } + // else handle create. + } else if err := s.groupMemberTable.Create(ctx, &groupMember); err != nil { + return sdkerrors.Wrap(err, "add member") + } + // In both cases (handle + update), we need to add the new member's weight to the group total weight. + err = math.Add(totalWeight, totalWeight, newMemberWeight) + if err != nil { + return err + } + } + // Update group in the groupTable. + g.TotalWeight = math.DecimalString(totalWeight) + g.Version++ + return s.groupTable.Save(ctx, g.GroupId, g) + } + + err := s.doUpdateGroup(ctx, req, action, "members updated") + if err != nil { + return nil, err + } + + return &group.MsgUpdateGroupMembersResponse{}, nil +} + +func (s serverImpl) UpdateGroupAdmin(goCtx context.Context, req *group.MsgUpdateGroupAdmin) (*group.MsgUpdateGroupAdminResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + action := func(g *group.GroupInfo) error { + g.Admin = req.NewAdmin + g.Version++ + + return s.groupTable.Save(ctx, g.GroupId, g) + } + + err := s.doUpdateGroup(ctx, req, action, "admin updated") + if err != nil { + return nil, err + } + + return &group.MsgUpdateGroupAdminResponse{}, nil +} + +func (s serverImpl) UpdateGroupMetadata(goCtx context.Context, req *group.MsgUpdateGroupMetadata) (*group.MsgUpdateGroupMetadataResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + action := func(g *group.GroupInfo) error { + g.Metadata = req.Metadata + g.Version++ + return s.groupTable.Save(ctx, g.GroupId, g) + } + + err := s.doUpdateGroup(ctx, req, action, "metadata updated") + if err != nil { + return nil, err + } + + return &group.MsgUpdateGroupMetadataResponse{}, nil +} + +func (s serverImpl) CreateGroupAccount(goCtx context.Context, req *group.MsgCreateGroupAccount) (*group.MsgCreateGroupAccountResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + admin, err := sdk.AccAddressFromBech32(req.GetAdmin()) + if err != nil { + return nil, sdkerrors.Wrap(err, "request admin") + } + policy := req.GetDecisionPolicy() + groupID := req.GetGroupID() + metadata := req.GetMetadata() + + g, err := s.getGroupInfo(ctx, groupID) + if err != nil { + return nil, err + } + groupAdmin, err := sdk.AccAddressFromBech32(g.Admin) + if err != nil { + return nil, sdkerrors.Wrap(err, "group admin") + } + // Only current group admin is authorized to create a group account for this group. + if !groupAdmin.Equals(admin) { + return nil, sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not group admin") + } + + // Generate group account address. + var accountAddr sdk.AccAddress + var accountDerivationKey []byte + // loop here in the rare case of a collision + for { + nextAccVal := s.groupAccountSeq.NextVal(ctx) + buf := bytes.NewBuffer(nil) + err = binary.Write(buf, binary.LittleEndian, nextAccVal) + if err != nil { + return nil, err + } + + accountDerivationKey = buf.Bytes() + accountID := s.key.Derive(accountDerivationKey) + accountAddr = accountID.Address() + + if s.accKeeper.GetAccount(ctx.Context, accountAddr) != nil { + // handle a rare collision + continue + } + + acc := s.accKeeper.NewAccount(ctx.Context, &authtypes.ModuleAccount{ + BaseAccount: &authtypes.BaseAccount{ + Address: accountAddr.String(), + }, + Name: accountAddr.String(), + }) + s.accKeeper.SetAccount(ctx.Context, acc) + + break + } + + groupAccount, err := group.NewGroupAccountInfo( + accountAddr, + groupID, + admin, + metadata, + 1, + policy, + accountDerivationKey, + ) + if err != nil { + return nil, err + } + + if err := s.groupAccountTable.Create(ctx, &groupAccount); err != nil { + return nil, sdkerrors.Wrap(err, "could not create group account") + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventCreateGroupAccount{Address: accountAddr.String()}) + if err != nil { + return nil, err + } + + return &group.MsgCreateGroupAccountResponse{Address: accountAddr.String()}, nil +} + +func (s serverImpl) UpdateGroupAccountAdmin(goCtx context.Context, req *group.MsgUpdateGroupAccountAdmin) (*group.MsgUpdateGroupAccountAdminResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + action := func(groupAccount *group.GroupAccountInfo) error { + groupAccount.Admin = req.NewAdmin + groupAccount.Version++ + return s.groupAccountTable.Save(ctx, groupAccount) + } + + err := s.doUpdateGroupAccount(ctx, req.Address, req.Admin, action, "group account admin updated") + if err != nil { + return nil, err + } + + return &group.MsgUpdateGroupAccountAdminResponse{}, nil +} + +func (s serverImpl) UpdateGroupAccountDecisionPolicy(goCtx context.Context, req *group.MsgUpdateGroupAccountDecisionPolicy) (*group.MsgUpdateGroupAccountDecisionPolicyResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + policy := req.GetDecisionPolicy() + + action := func(groupAccount *group.GroupAccountInfo) error { + err := groupAccount.SetDecisionPolicy(policy) + if err != nil { + return err + } + + groupAccount.Version++ + return s.groupAccountTable.Save(ctx, groupAccount) + } + + err := s.doUpdateGroupAccount(ctx, req.Address, req.Admin, action, "group account decision policy updated") + if err != nil { + return nil, err + } + + return &group.MsgUpdateGroupAccountDecisionPolicyResponse{}, nil +} + +func (s serverImpl) UpdateGroupAccountMetadata(goCtx context.Context, req *group.MsgUpdateGroupAccountMetadata) (*group.MsgUpdateGroupAccountMetadataResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + metadata := req.GetMetadata() + + action := func(groupAccount *group.GroupAccountInfo) error { + groupAccount.Metadata = metadata + groupAccount.Version++ + return s.groupAccountTable.Save(ctx, groupAccount) + } + + err := s.doUpdateGroupAccount(ctx, req.Address, req.Admin, action, "group account metadata updated") + if err != nil { + return nil, err + } + + return &group.MsgUpdateGroupAccountMetadataResponse{}, nil +} + +func (s serverImpl) CreateProposal(goCtx context.Context, req *group.MsgCreateProposal) (*group.MsgCreateProposalResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + accountAddress, err := sdk.AccAddressFromBech32(req.Address) + if err != nil { + return nil, sdkerrors.Wrap(err, "request group account") + } + metadata := req.Metadata + proposers := req.Proposers + msgs := req.GetMsgs() + + account, err := s.getGroupAccountInfo(ctx, accountAddress.Bytes()) + if err != nil { + return nil, sdkerrors.Wrap(err, "load group account") + } + + g, err := s.getGroupInfo(ctx, account.GroupId) + if err != nil { + return nil, sdkerrors.Wrap(err, "get group by account") + } + + // Only members of the group can submit a new proposal. + for i := range proposers { + if !s.groupMemberTable.Has(ctx, orm.PrimaryKey(&group.GroupMember{GroupId: g.GroupId, Member: &group.Member{Address: proposers[i]}})) { + return nil, sdkerrors.Wrapf(group.ErrUnauthorized, "not in group: %s", proposers[i]) + } + } + + // Check that if the messages require signers, they are all equal to the given group account. + if err := ensureMsgAuthZ(msgs, accountAddress); err != nil { + return nil, err + } + + blockTime, err := gogotypes.TimestampProto(ctx.BlockTime()) + if err != nil { + return nil, sdkerrors.Wrap(err, "block time conversion") + } + + policy := account.GetDecisionPolicy() + if policy == nil { + return nil, sdkerrors.Wrap(group.ErrEmpty, "nil policy") + } + + // Prevent proposal that can not succeed. + err = policy.Validate(g) + if err != nil { + return nil, err + } + + // Define proposal timout. + // The voting window begins as soon as the proposal is submitted. + timeout := policy.GetTimeout() + window, err := gogotypes.DurationFromProto(&timeout) + if err != nil { + return nil, sdkerrors.Wrap(err, "maxVotingWindow time conversion") + } + endTime, err := gogotypes.TimestampProto(ctx.BlockTime().Add(window)) + if err != nil { + return nil, sdkerrors.Wrap(err, "end time conversion") + } + + m := &group.Proposal{ + ProposalId: s.proposalTable.Sequence().PeekNextVal(ctx), + Address: req.Address, + Metadata: metadata, + Proposers: proposers, + SubmittedAt: *blockTime, + GroupVersion: g.Version, + GroupAccountVersion: account.Version, + Result: group.ProposalResultUnfinalized, + Status: group.ProposalStatusSubmitted, + ExecutorResult: group.ProposalExecutorResultNotRun, + Timeout: *endTime, + VoteState: group.Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + } + if err := m.SetMsgs(msgs); err != nil { + return nil, sdkerrors.Wrap(err, "create proposal") + } + + id, err := s.proposalTable.Create(ctx, m) + if err != nil { + return nil, sdkerrors.Wrap(err, "create proposal") + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventCreateProposal{ProposalId: id}) + if err != nil { + return nil, err + } + + // Try to execute proposal immediately + if req.Exec == group.Exec_EXEC_TRY { + // Consider proposers as Yes votes + for i := range proposers { + ctx.GasMeter().ConsumeGas(gasCostPerIteration, "vote on proposal") + _, err = s.Vote(ctx, &group.MsgVote{ + ProposalId: id, + Voter: proposers[i], + Choice: group.Choice_CHOICE_YES, + }) + if err != nil { + return &group.MsgCreateProposalResponse{ProposalId: id}, sdkerrors.Wrap(err, "The proposal was created but failed on vote") + } + } + // Then try to execute the proposal + _, err = s.Exec(ctx, &group.MsgExec{ + ProposalId: id, + // We consider the first proposer as the MsgExecRequest signer + // but that could be revisited (eg using the group account) + Signer: proposers[0], + }) + if err != nil { + return &group.MsgCreateProposalResponse{ProposalId: id}, sdkerrors.Wrap(err, "The proposal was created but failed on exec") + } + } + + return &group.MsgCreateProposalResponse{ProposalId: id}, nil +} + +func (s serverImpl) Vote(goCtx context.Context, req *group.MsgVote) (*group.MsgVoteResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + id := req.ProposalId + choice := req.Choice + metadata := req.Metadata + + blockTime, err := gogotypes.TimestampProto(ctx.BlockTime()) + if err != nil { + return nil, err + } + proposal, err := s.getProposal(ctx, id) + if err != nil { + return nil, err + } + // Ensure that we can still accept votes for this proposal. + if proposal.Status != group.ProposalStatusSubmitted { + return nil, sdkerrors.Wrap(group.ErrInvalid, "proposal not open for voting") + } + votingPeriodEnd, err := gogotypes.TimestampFromProto(&proposal.Timeout) + if err != nil { + return nil, err + } + if votingPeriodEnd.Before(ctx.BlockTime()) || votingPeriodEnd.Equal(ctx.BlockTime()) { + return nil, sdkerrors.Wrap(group.ErrExpired, "voting period has ended already") + } + + // Ensure that group account hasn't been modified since the proposal submission. + address, err := sdk.AccAddressFromBech32(proposal.Address) + if err != nil { + return nil, sdkerrors.Wrap(err, "group account") + } + accountInfo, err := s.getGroupAccountInfo(ctx, address.Bytes()) + if err != nil { + return nil, sdkerrors.Wrap(err, "load group account") + } + if proposal.GroupAccountVersion != accountInfo.Version { + return nil, sdkerrors.Wrap(group.ErrModified, "group account was modified") + } + + // Ensure that group hasn't been modified since the proposal submission. + electorate, err := s.getGroupInfo(ctx, accountInfo.GroupId) + if err != nil { + return nil, err + } + if electorate.Version != proposal.GroupVersion { + return nil, sdkerrors.Wrap(group.ErrModified, "group was modified") + } + + // Count and store votes. + voterAddr := req.Voter + voter := group.GroupMember{GroupId: electorate.GroupId, Member: &group.Member{Address: voterAddr}} + if err := s.groupMemberTable.GetOne(ctx, orm.PrimaryKey(&voter), &voter); err != nil { + return nil, sdkerrors.Wrapf(err, "address: %s", voterAddr) + } + newVote := group.Vote{ + ProposalId: id, + Voter: voterAddr, + Choice: choice, + Metadata: metadata, + SubmittedAt: *blockTime, + } + if err := proposal.VoteState.Add(newVote, voter.Member.Weight); err != nil { + return nil, sdkerrors.Wrap(err, "add new vote") + } + + // The ORM will return an error if the vote already exists, + // making sure than a voter hasn't already voted. + if err := s.voteTable.Create(ctx, &newVote); err != nil { + return nil, sdkerrors.Wrap(err, "store vote") + } + + // Run tally with new votes to close early. + if err := doTally(ctx, &proposal, electorate, accountInfo); err != nil { + return nil, err + } + + if err = s.proposalTable.Save(ctx, id, &proposal); err != nil { + return nil, err + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventVote{ProposalId: id}) + if err != nil { + return nil, err + } + + // Try to execute proposal immediately + if req.Exec == group.Exec_EXEC_TRY { + _, err = s.Exec(ctx, &group.MsgExec{ + ProposalId: id, + Signer: voterAddr, + }) + if err != nil { + return nil, err + } + } + + return &group.MsgVoteResponse{}, nil +} + +// doTally updates the proposal status and tally if necessary based on the group account's decision policy. +func doTally(ctx types.Context, p *group.Proposal, electorate group.GroupInfo, accountInfo group.GroupAccountInfo) error { + policy := accountInfo.GetDecisionPolicy() + submittedAt, err := gogotypes.TimestampFromProto(&p.SubmittedAt) + if err != nil { + return err + } + switch result, err := policy.Allow(p.VoteState, electorate.TotalWeight, ctx.BlockTime().Sub(submittedAt)); { + case err != nil: + return sdkerrors.Wrap(err, "policy execution") + case result.Allow && result.Final: + p.Result = group.ProposalResultAccepted + p.Status = group.ProposalStatusClosed + case !result.Allow && result.Final: + p.Result = group.ProposalResultRejected + p.Status = group.ProposalStatusClosed + } + return nil +} + +func (s serverImpl) VoteAgg(goCtx context.Context, req *group.MsgVoteAgg) (*group.MsgVoteAggResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + id := req.ProposalId + choices := req.Votes + metadata := req.Metadata + votesExpire := req.Expiry + + blockTime, err := gogotypes.TimestampProto(ctx.BlockTime()) + if err != nil { + return nil, err + } + + if votesExpire.Compare(blockTime) <= 0 { + return nil, sdkerrors.Wrap(group.ErrExpired, "the aggregated votes have expired") + } + + proposal, err := s.getProposal(ctx, id) + if err != nil { + return nil, err + } + // Ensure that we can still accept votes for this proposal. + if proposal.Status != group.ProposalStatusSubmitted { + return nil, sdkerrors.Wrap(group.ErrInvalid, "proposal not open for voting") + } + if proposal.Timeout.Compare(blockTime) <= 0 { + return nil, sdkerrors.Wrap(group.ErrExpired, "voting period has ended already") + } + + // Ensure that group account hasn't been modified since the proposal submission. + address, err := sdk.AccAddressFromBech32(proposal.Address) + if err != nil { + return nil, sdkerrors.Wrap(err, "group account") + } + accountInfo, err := s.getGroupAccountInfo(ctx, address.Bytes()) + if err != nil { + return nil, sdkerrors.Wrap(err, "load group account") + } + if proposal.GroupAccountVersion != accountInfo.Version { + return nil, sdkerrors.Wrap(group.ErrModified, "group account was modified") + } + + // Ensure that group hasn't been modified since the proposal submission. + electorate, err := s.getGroupInfo(ctx, accountInfo.GroupId) + if err != nil { + return nil, err + } + if electorate.Version != proposal.GroupVersion { + return nil, sdkerrors.Wrap(group.ErrModified, "group was modified") + } + + membersIter, err := s.groupMemberByGroupIndex.Get(ctx, electorate.GroupId) + if err != nil { + return nil, err + } + + var votes []group.Vote + var weights []string + choiceMap := make(map[group.Choice]bool, len(group.Choice_name)) + pkMap := make(map[group.Choice][]cryptotypes.PubKey, len(group.Choice_name)) + msgMap := make(map[group.Choice][]byte, len(group.Choice_name)) + for i := 0; ; i++ { + var mem group.GroupMember + _, err := membersIter.LoadNext(&mem) + if err != nil { + if orm.ErrIteratorDone.Is(err) { + if i < len(choices) { + return nil, sdkerrors.Wrap(group.ErrInvalid, "too many votes") + } + break + } + return nil, err + } + + memAddr, err := sdk.AccAddressFromBech32(mem.Member.Address) + if err != nil { + return nil, err + } + + if i >= len(choices) { + return nil, sdkerrors.Wrap(group.ErrInvalid, "not enough votes") + } + + acc := s.accKeeper.GetAccount(ctx.Context, memAddr) + if acc == nil { + return nil, sdkerrors.Wrapf(group.ErrInvalid, "account %s does not exist", memAddr.String()) + } + pk := acc.GetPubKey() + if pk == nil { + return nil, sdkerrors.Wrapf(group.ErrInvalid, "public key for account %s not set yet", memAddr.String()) + } + + if choices[i] != group.Choice_CHOICE_UNSPECIFIED { + vote := group.Vote{ + ProposalId: id, + Voter: mem.Member.Address, + Choice: choices[i], + Metadata: metadata, + SubmittedAt: *blockTime, + } + votes = append(votes, vote) + weights = append(weights, mem.Member.Weight) + + _, ok := choiceMap[choices[i]] + if !ok { + choiceMap[choices[i]] = true + msg := group.MsgVoteBasic{ + ProposalId: id, + Choice: choices[i], + Expiry: votesExpire, + } + msgMap[choices[i]] = msg.GetSignBytes() + } + pkMap[choices[i]] = append(pkMap[choices[i]], pk) + } + } + + // calculate and consume gas before the verification of the aggregated signature + numChoice := uint64(len(choiceMap)) + numPk := uint64(len(votes)) + params := s.accKeeper.GetParams(ctx.Context) + err = DefaultAggSigVerifyGasConsumer(ctx.GasMeter(), numPk, numChoice, params) + if err != nil { + return nil, sdkerrors.Wrap(err, "gas consumption for verifying aggregated signature") + } + + msgBytes := make([][]byte, 0, numChoice) + pkss := make([][]cryptotypes.PubKey, 0, numChoice) + for c := range msgMap { + msgBytes = append(msgBytes, msgMap[c]) + pkss = append(pkss, pkMap[c]) + } + + if err = group.VerifyAggregateSignature(msgBytes, false, req.AggSig, pkss); err != nil { + return nil, err + } + + // Count and store votes. + for i := range votes { + err := proposal.VoteState.Add(votes[i], weights[i]) + if err == nil { + // If the vote already exists, skip the new vote + if err := s.voteTable.Create(ctx, &votes[i]); err != nil { + if orm.ErrUniqueConstraint.Is(err) { + if err := proposal.VoteState.Sub(votes[i], weights[i]); err != nil { + return nil, sdkerrors.Wrap(err, "sub new vote") + } + continue + } + return nil, err + } + } + } + + if err := doTally(ctx, &proposal, electorate, accountInfo); err != nil { + return nil, err + } + + if err = s.proposalTable.Save(ctx, id, &proposal); err != nil { + return nil, err + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventVote{ProposalId: id}) + if err != nil { + return nil, err + } + + // Try to execute proposal immediately + if req.Exec == group.Exec_EXEC_TRY { + _, err = s.Exec(ctx, &group.MsgExec{ + ProposalId: id, + Signer: req.Sender, + }) + if err != nil { + return nil, err + } + } + + return &group.MsgVoteAggResponse{}, nil +} + +// Exec executes the messages from a proposal. +func (s serverImpl) Exec(goCtx context.Context, req *group.MsgExec) (*group.MsgExecResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + id := req.ProposalId + + proposal, err := s.getProposal(ctx, id) + if err != nil { + return nil, err + } + + if proposal.Status != group.ProposalStatusSubmitted && proposal.Status != group.ProposalStatusClosed { + return nil, sdkerrors.Wrapf(group.ErrInvalid, "not possible with proposal status %s", proposal.Status.String()) + } + + address, err := sdk.AccAddressFromBech32(proposal.Address) + if err != nil { + return nil, sdkerrors.Wrap(err, "group account") + } + accountInfo, err := s.getGroupAccountInfo(ctx, address.Bytes()) + if err != nil { + return nil, sdkerrors.Wrap(err, "load group account") + } + + storeUpdates := func() (*group.MsgExecResponse, error) { + if err := s.proposalTable.Save(ctx, id, &proposal); err != nil { + return nil, err + } + return &group.MsgExecResponse{}, nil + } + + if proposal.Status == group.ProposalStatusSubmitted { + // Ensure that group account hasn't been modified before tally. + if proposal.GroupAccountVersion != accountInfo.Version { + proposal.Result = group.ProposalResultUnfinalized + proposal.Status = group.ProposalStatusAborted + return storeUpdates() + } + + electorate, err := s.getGroupInfo(ctx, accountInfo.GroupId) + if err != nil { + return nil, sdkerrors.Wrap(err, "load group") + } + + // Ensure that group hasn't been modified before tally. + if electorate.Version != proposal.GroupVersion { + proposal.Result = group.ProposalResultUnfinalized + proposal.Status = group.ProposalStatusAborted + return storeUpdates() + } + if err := doTally(ctx, &proposal, electorate, accountInfo); err != nil { + return nil, err + } + } + + // Execute proposal payload. + if proposal.Status == group.ProposalStatusClosed && proposal.Result == group.ProposalResultAccepted && proposal.ExecutorResult != group.ProposalExecutorResultSuccess { + logger := ctx.Logger().With("module", fmt.Sprintf("x/%s", group.ModuleName)) + // Cashing context so that we don't update the store in case of failure. + ctx, flush := ctx.CacheContext() + + err := s.execMsgs(sdk.WrapSDKContext(ctx), accountInfo.DerivationKey, proposal) + if err != nil { + proposal.ExecutorResult = group.ProposalExecutorResultFailure + proposalType := reflect.TypeOf(proposal).String() + logger.Info("proposal execution failed", "cause", err, "type", proposalType, "proposalID", id) + } else { + proposal.ExecutorResult = group.ProposalExecutorResultSuccess + flush() + } + } + + // Update proposal in proposalTable + res, err := storeUpdates() + if err != nil { + return nil, err + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventExec{ProposalId: id}) + if err != nil { + return nil, err + } + + return res, nil +} + +func (s serverImpl) CreatePoll(goCtx context.Context, req *group.MsgCreatePoll) (*group.MsgCreatePollResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + creator := req.Creator + groupId := req.GroupId + endTime := req.Timeout + metadata := req.Metadata + title := req.Title + options := req.Options + limit := req.VoteLimit + + g, err := s.getGroupInfo(ctx, groupId) + if err != nil { + return nil, sdkerrors.Wrap(err, "get group by account") + } + + // Only members of the group can submit a new poll. + if !s.groupMemberTable.Has(ctx, orm.PrimaryKey(&group.GroupMember{GroupId: g.GroupId, Member: &group.Member{Address: creator}})) { + return nil, sdkerrors.Wrapf(group.ErrUnauthorized, "not in group: %s", creator) + } + + blockTime, err := gogotypes.TimestampProto(ctx.BlockTime()) + if err != nil { + return nil, sdkerrors.Wrap(err, "block time conversion") + } + + if endTime.Compare(blockTime) <= 0 { + return nil, sdkerrors.Wrap(group.ErrExpired, "poll already expired") + } + + m := &group.Poll{ + PollId: s.pollTable.Sequence().PeekNextVal(ctx), + GroupId: groupId, + Title: title, + Options: options, + Creator: creator, + VoteLimit: limit, + Metadata: metadata, + SubmittedAt: *blockTime, + GroupVersion: g.Version, + Status: group.PollStatusSubmitted, + Timeout: endTime, + } + + id, err := s.pollTable.Create(ctx, m) + if err != nil { + return nil, sdkerrors.Wrap(err, "create poll") + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventCreatePoll{PollId: id}) + if err != nil { + return nil, err + } + + return &group.MsgCreatePollResponse{PollId: id}, nil +} + +func (s serverImpl) VotePoll(goCtx context.Context, req *group.MsgVotePoll) (*group.MsgVotePollResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + id := req.PollId + options := req.Options + metadata := req.Metadata + + blockTime, err := gogotypes.TimestampProto(ctx.BlockTime()) + if err != nil { + return nil, err + } + poll, err := s.getPoll(ctx, id) + if err != nil { + return nil, err + } + // Ensure that we can still accept votes for this poll. + if poll.Status != group.PollStatusSubmitted { + return nil, sdkerrors.Wrap(group.ErrInvalid, "poll not open for voting") + } + if poll.Timeout.Compare(blockTime) <= 0 { + poll.Status = group.PollStatusClosed + if err = s.pollTable.Save(ctx, id, &poll); err != nil { + return nil, err + } + return nil, sdkerrors.Wrap(group.ErrExpired, "voting period for the poll has ended") + } + + if err := assertOptionsSubset(options, poll.Options, "options"); err != nil { + return nil, err + } + + if len(options.Titles) > int(poll.VoteLimit) { + return nil, sdkerrors.Wrap(group.ErrInvalid, "voter options exceed limit") + } + + // Ensure that group hasn't been modified since the proposal submission. + electorate, err := s.getGroupInfo(ctx, poll.GroupId) + if err != nil { + return nil, err + } + if electorate.Version != poll.GroupVersion { + return nil, sdkerrors.Wrap(group.ErrModified, "group was modified") + } + + // Count and store votes. + voterAddr := req.Voter + voter := group.GroupMember{GroupId: electorate.GroupId, Member: &group.Member{Address: voterAddr}} + if err := s.groupMemberTable.GetOne(ctx, orm.PrimaryKey(&voter), &voter); err != nil { + return nil, sdkerrors.Wrapf(err, "address: %s", voterAddr) + } + + newVote := group.VotePoll{ + PollId: id, + Voter: voterAddr, + Options: options, + Metadata: metadata, + SubmittedAt: *blockTime, + } + if len(poll.VoteState.Counts) == 0 { + poll.VoteState.Counts = make(map[string]string) + } + + if err := poll.VoteState.Add(newVote, voter.Member.Weight); err != nil { + return nil, sdkerrors.Wrap(err, "add new vote") + } + + // The ORM will return an error if the vote already exists, + // making sure than a voter hasn't already voted. + if err := s.votePollTable.Create(ctx, &newVote); err != nil { + return nil, sdkerrors.Wrap(err, "store vote") + } + + if err = s.pollTable.Save(ctx, id, &poll); err != nil { + return nil, err + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventVotePoll{PollId: id}) + if err != nil { + return nil, err + } + + return &group.MsgVotePollResponse{}, nil +} + +// VotePollAgg processes an aggregated votes for poll. The votes are signed and aggregated +// on an option-basis instead of voter-basis, which means the verification time of the +// aggregated signature is linear of the number of options instead of the number of voters. +// The total number of options should be kept small so the verification of the aggregated signature can be more efficient. +func (s serverImpl) VotePollAgg(goCtx context.Context, req *group.MsgVotePollAgg) (*group.MsgVotePollAggResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + id := req.PollId + votes := req.Votes + metadata := req.Metadata + votesExpire := req.Expiry + + blockTime, err := gogotypes.TimestampProto(ctx.BlockTime()) + if err != nil { + return nil, err + } + + if votesExpire.Compare(blockTime) <= 0 { + return nil, sdkerrors.Wrap(group.ErrExpired, "the aggregated votes have expired") + } + + poll, err := s.getPoll(ctx, id) + if err != nil { + return nil, err + } + // Ensure that we can still accept votes for this poll. + if poll.Status != group.PollStatusSubmitted { + return nil, sdkerrors.Wrap(group.ErrInvalid, "poll not open for voting") + } + if poll.Timeout.Compare(blockTime) <= 0 { + poll.Status = group.PollStatusClosed + if err = s.pollTable.Save(ctx, id, &poll); err != nil { + return nil, err + } + return nil, sdkerrors.Wrap(group.ErrExpired, "voting period for the poll has ended") + } + + // Ensure that group hasn't been modified since the proposal submission. + electorate, err := s.getGroupInfo(ctx, poll.GroupId) + if err != nil { + return nil, err + } + if electorate.Version != poll.GroupVersion { + return nil, sdkerrors.Wrap(group.ErrModified, "group was modified") + } + + for _, v := range votes { + if err = assertOptionsSubset(v, poll.Options, "aggregated vote for poll"); err != nil { + return nil, sdkerrors.Wrap(group.ErrInvalid, err.Error()) + } + if len(v.Titles) > int(poll.VoteLimit) { + return nil, sdkerrors.Wrap(group.ErrInvalid, "voter options exceed limit") + } + } + + membersIter, err := s.groupMemberByGroupIndex.Get(ctx, electorate.GroupId) + if err != nil { + return nil, err + } + + // Count and store votes. + var weights []string + pkMap := make(map[string][]cryptotypes.PubKey, len(poll.Options.Titles)) + msgMap := make(map[string][]byte, len(poll.Options.Titles)) + var votesStore []group.VotePoll + numPk := uint64(0) + for i := 0; ; i++ { + var mem group.GroupMember + _, err := membersIter.LoadNext(&mem) + if err != nil { + if orm.ErrIteratorDone.Is(err) { + if i < len(votes) { + return nil, sdkerrors.Wrap(group.ErrInvalid, "too many votes") + } + break + } + return nil, err + } + + memAddr, err := sdk.AccAddressFromBech32(mem.Member.Address) + if err != nil { + return nil, err + } + + if i >= len(votes) { + return nil, sdkerrors.Wrap(group.ErrInvalid, "not enough votes") + } + + acc := s.accKeeper.GetAccount(ctx.Context, memAddr) + if acc == nil { + return nil, sdkerrors.Wrapf(group.ErrInvalid, "account %s does not exist", memAddr.String()) + } + pk := acc.GetPubKey() + if pk == nil { + return nil, sdkerrors.Wrapf(group.ErrInvalid, "public key for account %s not set yet", memAddr.String()) + } + + if len(votes[i].Titles) != 0 { + vote := group.VotePoll{ + PollId: id, + Voter: mem.Member.Address, + Options: votes[i], + Metadata: metadata, + SubmittedAt: *blockTime, + } + votesStore = append(votesStore, vote) + weights = append(weights, mem.Member.Weight) + for _, ot := range votes[i].Titles { + if _, ok := msgMap[ot]; !ok { + msg := group.MsgVotePollBasic{ + PollId: id, + Option: ot, + Expiry: votesExpire, + } + msgMap[ot] = msg.GetSignBytes() + } + pkMap[ot] = append(pkMap[ot], pk) + numPk++ + } + } + } + + // calculate and consume gas before the verification of the aggregated signature + numVotedOption := uint64(len(msgMap)) + params := s.accKeeper.GetParams(ctx.Context) + err = DefaultAggSigVerifyGasConsumer(ctx.GasMeter(), numPk, numVotedOption, params) + if err != nil { + return nil, sdkerrors.Wrap(err, "gas consumption for verifying aggregated signature") + } + + msgBytes := make([][]byte, 0, numVotedOption) + pkss := make([][]cryptotypes.PubKey, 0, numVotedOption) + for c := range msgMap { + msgBytes = append(msgBytes, msgMap[c]) + pkss = append(pkss, pkMap[c]) + } + + if err = group.VerifyAggregateSignature(msgBytes, false, req.AggSig, pkss); err != nil { + return nil, err + } + + // Count and store votes. + if len(poll.VoteState.Counts) == 0 { + poll.VoteState.Counts = make(map[string]string, len(votesStore)) + } + + for i := range votesStore { + // skip the vote if error + err := poll.VoteState.Add(votesStore[i], weights[i]) + if err != nil { + continue + } + // If the vote already exists, skip the new vote + if err := s.votePollTable.Create(ctx, &votesStore[i]); err != nil { + if orm.ErrUniqueConstraint.Is(err) { + if err := poll.VoteState.Sub(votesStore[i], weights[i]); err != nil { + return nil, sdkerrors.Wrap(err, "sub new vote") + } + continue + } + return nil, err + } + } + + if err = s.pollTable.Save(ctx, id, &poll); err != nil { + return nil, err + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventVotePoll{PollId: id}) + if err != nil { + return nil, err + } + + return &group.MsgVotePollAggResponse{}, nil +} + +type authNGroupReq interface { + GetGroupID() uint64 + GetAdmin() string +} + +type actionFn func(m *group.GroupInfo) error +type groupAccountActionFn func(m *group.GroupAccountInfo) error + +// doUpdateGroupAccount first makes sure that the group account admin initiated the group account update, +// before performing the group account update and emitting an event. +func (s serverImpl) doUpdateGroupAccount(ctx types.Context, groupAccount string, admin string, action groupAccountActionFn, note string) error { + groupAccountAddress, err := sdk.AccAddressFromBech32(groupAccount) + if err != nil { + return sdkerrors.Wrap(err, "group admin") + } + + groupAccountInfo, err := s.getGroupAccountInfo(ctx, groupAccountAddress.Bytes()) + if err != nil { + return sdkerrors.Wrap(err, "load group account") + } + + groupAccountAdmin, err := sdk.AccAddressFromBech32(admin) + if err != nil { + return sdkerrors.Wrap(err, "group account admin") + } + + // Only current group account admin is authorized to update a group account. + if groupAccountAdmin.String() != groupAccountInfo.Admin { + return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not group account admin") + } + + if err := action(&groupAccountInfo); err != nil { + return sdkerrors.Wrap(err, note) + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventUpdateGroupAccount{Address: admin}) + if err != nil { + return err + } + + return nil +} + +// doUpdateGroup first makes sure that the group admin initiated the group update, +// before performing the group update and emitting an event. +func (s serverImpl) doUpdateGroup(ctx types.Context, req authNGroupReq, action actionFn, note string) error { + err := s.doAuthenticated(ctx, req, action, note) + if err != nil { + return err + } + + err = ctx.EventManager().EmitTypedEvent(&group.EventUpdateGroup{GroupId: req.GetGroupID()}) + if err != nil { + return err + } + + return nil +} + +// doAuthenticated makes sure that the group admin initiated the request, +// and perform the provided action on the group. +func (s serverImpl) doAuthenticated(ctx types.Context, req authNGroupReq, action actionFn, note string) error { + group, err := s.getGroupInfo(ctx, req.GetGroupID()) + if err != nil { + return err + } + admin, err := sdk.AccAddressFromBech32(group.Admin) + if err != nil { + return sdkerrors.Wrap(err, "group admin") + } + reqAdmin, err := sdk.AccAddressFromBech32(req.GetAdmin()) + if err != nil { + return sdkerrors.Wrap(err, "request admin") + } + if !admin.Equals(reqAdmin) { + return sdkerrors.Wrap(sdkerrors.ErrUnauthorized, "not group admin") + } + if err := action(&group); err != nil { + return sdkerrors.Wrap(err, note) + } + return nil +} + +func assertOptionsSubset(a group.Options, b group.Options, description string) error { + for _, x := range a.Titles { + foundX := false + for _, y := range b.Titles { + if x == y { + foundX = true + break + } + } + if !foundX { + return sdkerrors.Wrap(group.ErrInvalid, description) + } + } + return nil +} diff --git a/x/group/server/operations.go b/x/group/server/operations.go new file mode 100644 index 0000000000..7d80380e7a --- /dev/null +++ b/x/group/server/operations.go @@ -0,0 +1,22 @@ +package server + +import ( + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/simulation" +) + +// WeightedOperations returns all the group module operations with their respective weights. +func (s serverImpl) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { + + interfaceRegistry := types.NewInterfaceRegistry() + queryClient := group.NewQueryClient(s.key) + return simulation.WeightedOperations( + simState.AppParams, simState.Cdc, + s.accKeeper, s.bankKeeper, queryClient, codec.NewProtoCodec(interfaceRegistry), + ) +} diff --git a/x/group/server/proposal_executor.go b/x/group/server/proposal_executor.go new file mode 100644 index 0000000000..65e48249bc --- /dev/null +++ b/x/group/server/proposal_executor.go @@ -0,0 +1,40 @@ +package server + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + + "github.com/cosmos/cosmos-sdk/regen/types/module/server" + "github.com/cosmos/cosmos-sdk/x/group" +) + +func (s serverImpl) execMsgs(ctx context.Context, derivationKey []byte, proposal group.Proposal) error { + derivedKey := s.key.Derive(derivationKey) + msgs := proposal.GetMsgs() + + for _, msg := range msgs { + var reply interface{} + + // Execute the message using the derived key, + // this will verify that the message signer is the group account. + err := derivedKey.Invoke(ctx, server.TypeURL(msg), msg, reply) + if err != nil { + return err + } + } + return nil +} + +// ensureMsgAuthZ checks that if a message requires signers that all of them are equal to the given group account. +func ensureMsgAuthZ(msgs []sdk.Msg, groupAccount sdk.AccAddress) error { + for i := range msgs { + for _, acct := range msgs[i].GetSigners() { + if !groupAccount.Equals(acct) { + return errors.Wrap(errors.ErrUnauthorized, "msg does not have group account authorization") + } + } + } + return nil +} diff --git a/x/group/server/query_server.go b/x/group/server/query_server.go new file mode 100644 index 0000000000..8ee510de86 --- /dev/null +++ b/x/group/server/query_server.go @@ -0,0 +1,414 @@ +package server + +import ( + "context" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/cosmos/cosmos-sdk/types/query" + "github.com/cosmos/cosmos-sdk/x/group" +) + +func (s serverImpl) GroupInfo(goCtx context.Context, request *group.QueryGroupInfoRequest) (*group.QueryGroupInfoResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + groupID := request.GroupId + groupInfo, err := s.getGroupInfo(ctx, groupID) + if err != nil { + return nil, err + } + + return &group.QueryGroupInfoResponse{Info: &groupInfo}, nil +} + +func (s serverImpl) getGroupInfo(goCtx context.Context, id uint64) (group.GroupInfo, error) { + ctx := types.UnwrapSDKContext(goCtx) + var obj group.GroupInfo + _, err := s.groupTable.GetOne(ctx, id, &obj) + return obj, err +} + +func (s serverImpl) GroupAccountInfo(goCtx context.Context, request *group.QueryGroupAccountInfoRequest) (*group.QueryGroupAccountInfoResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Address) + if err != nil { + return nil, err + } + groupAccountInfo, err := s.getGroupAccountInfo(ctx, addr) + if err != nil { + return nil, err + } + + return &group.QueryGroupAccountInfoResponse{Info: &groupAccountInfo}, nil +} + +func (s serverImpl) getGroupAccountInfo(goCtx context.Context, accountAddress sdk.AccAddress) (group.GroupAccountInfo, error) { + ctx := types.UnwrapSDKContext(goCtx) + var obj group.GroupAccountInfo + return obj, s.groupAccountTable.GetOne(ctx, orm.AddLengthPrefix(accountAddress.Bytes()), &obj) +} + +func (s serverImpl) GroupMembers(goCtx context.Context, request *group.QueryGroupMembersRequest) (*group.QueryGroupMembersResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + groupID := request.GroupId + it, err := s.getGroupMembers(ctx, groupID, request.Pagination) + if err != nil { + return nil, err + } + + var members []*group.GroupMember + pageRes, err := orm.Paginate(it, request.Pagination, &members) + if err != nil { + return nil, err + } + + return &group.QueryGroupMembersResponse{ + Members: members, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getGroupMembers(goCtx context.Context, id uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { + ctx := types.UnwrapSDKContext(goCtx) + return s.groupMemberByGroupIndex.GetPaginated(ctx, id, pageRequest) +} + +func (s serverImpl) GroupsByAdmin(goCtx context.Context, request *group.QueryGroupsByAdminRequest) (*group.QueryGroupsByAdminResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Admin) + if err != nil { + return nil, err + } + it, err := s.getGroupsByAdmin(ctx, addr, request.Pagination) + if err != nil { + return nil, err + } + + var groups []*group.GroupInfo + pageRes, err := orm.Paginate(it, request.Pagination, &groups) + if err != nil { + return nil, err + } + + return &group.QueryGroupsByAdminResponse{ + Groups: groups, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getGroupsByAdmin(goCtx context.Context, admin sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { + ctx := types.UnwrapSDKContext(goCtx) + return s.groupByAdminIndex.GetPaginated(ctx, admin.Bytes(), pageRequest) +} + +func (s serverImpl) GroupAccountsByGroup(goCtx context.Context, request *group.QueryGroupAccountsByGroupRequest) (*group.QueryGroupAccountsByGroupResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + groupID := request.GroupId + it, err := s.getGroupAccountsByGroup(ctx, groupID, request.Pagination) + if err != nil { + return nil, err + } + + var accounts []*group.GroupAccountInfo + pageRes, err := orm.Paginate(it, request.Pagination, &accounts) + if err != nil { + return nil, err + } + + return &group.QueryGroupAccountsByGroupResponse{ + GroupAccounts: accounts, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getGroupAccountsByGroup(ctx types.Context, id uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.groupAccountByGroupIndex.GetPaginated(ctx, id, pageRequest) +} + +func (s serverImpl) GroupAccountsByAdmin(goCtx context.Context, request *group.QueryGroupAccountsByAdminRequest) (*group.QueryGroupAccountsByAdminResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Admin) + if err != nil { + return nil, err + } + it, err := s.getGroupAccountsByAdmin(ctx, addr, request.Pagination) + if err != nil { + return nil, err + } + + var accounts []*group.GroupAccountInfo + pageRes, err := orm.Paginate(it, request.Pagination, &accounts) + if err != nil { + return nil, err + } + + return &group.QueryGroupAccountsByAdminResponse{ + GroupAccounts: accounts, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getGroupAccountsByAdmin(ctx types.Context, admin sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.groupAccountByAdminIndex.GetPaginated(ctx, admin.Bytes(), pageRequest) +} + +func (s serverImpl) Proposal(goCtx context.Context, request *group.QueryProposalRequest) (*group.QueryProposalResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + proposalID := request.ProposalId + proposal, err := s.getProposal(ctx, proposalID) + if err != nil { + return nil, err + } + + return &group.QueryProposalResponse{Proposal: &proposal}, nil +} + +func (s serverImpl) ProposalsByGroupAccount(goCtx context.Context, request *group.QueryProposalsByGroupAccountRequest) (*group.QueryProposalsByGroupAccountResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Address) + if err != nil { + return nil, err + } + it, err := s.getProposalsByGroupAccount(ctx, addr, request.Pagination) + if err != nil { + return nil, err + } + + var proposals []*group.Proposal + pageRes, err := orm.Paginate(it, request.Pagination, &proposals) + if err != nil { + return nil, err + } + + return &group.QueryProposalsByGroupAccountResponse{ + Proposals: proposals, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getProposalsByGroupAccount(ctx types.Context, account sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.proposalByGroupAccountIndex.GetPaginated(ctx, account.Bytes(), pageRequest) +} + +func (s serverImpl) getProposal(ctx types.Context, proposalID uint64) (group.Proposal, error) { + var p group.Proposal + if _, err := s.proposalTable.GetOne(ctx, proposalID, &p); err != nil { + return group.Proposal{}, sdkerrors.Wrap(err, "load proposal") + } + return p, nil +} + +func (s serverImpl) VoteByProposalVoter(goCtx context.Context, request *group.QueryVoteByProposalVoterRequest) (*group.QueryVoteByProposalVoterResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Voter) + if err != nil { + return nil, err + } + proposalID := request.ProposalId + vote, err := s.getVote(ctx, proposalID, addr) + if err != nil { + return nil, err + } + return &group.QueryVoteByProposalVoterResponse{ + Vote: &vote, + }, nil +} + +func (s serverImpl) VotesByProposal(goCtx context.Context, request *group.QueryVotesByProposalRequest) (*group.QueryVotesByProposalResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + proposalID := request.ProposalId + it, err := s.getVotesByProposal(ctx, proposalID, request.Pagination) + if err != nil { + return nil, err + } + + var votes []*group.Vote + pageRes, err := orm.Paginate(it, request.Pagination, &votes) + if err != nil { + return nil, err + } + + return &group.QueryVotesByProposalResponse{ + Votes: votes, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) VotesByVoter(goCtx context.Context, request *group.QueryVotesByVoterRequest) (*group.QueryVotesByVoterResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Voter) + if err != nil { + return nil, err + } + it, err := s.getVotesByVoter(ctx, addr, request.Pagination) + if err != nil { + return nil, err + } + + var votes []*group.Vote + pageRes, err := orm.Paginate(it, request.Pagination, &votes) + if err != nil { + return nil, err + } + + return &group.QueryVotesByVoterResponse{ + Votes: votes, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getVote(ctx types.Context, proposalID uint64, voter sdk.AccAddress) (group.Vote, error) { + var v group.Vote + return v, s.voteTable.GetOne(ctx, orm.PrimaryKey(&group.Vote{ProposalId: proposalID, Voter: voter.String()}), &v) +} + +func (s serverImpl) getVotesByProposal(ctx types.Context, proposalID uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.voteByProposalIndex.GetPaginated(ctx, proposalID, pageRequest) +} + +func (s serverImpl) getVotesByVoter(ctx types.Context, voter sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.voteByVoterIndex.GetPaginated(ctx, voter.Bytes(), pageRequest) +} + +func (s serverImpl) Poll(goCtx context.Context, request *group.QueryPollRequest) (*group.QueryPollResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + pollID := request.PollId + poll, err := s.getPoll(ctx, pollID) + if err != nil { + return nil, err + } + + return &group.QueryPollResponse{Poll: &poll}, nil +} + +func (s serverImpl) getPoll(ctx types.Context, pollID uint64) (group.Poll, error) { + var p group.Poll + if _, err := s.pollTable.GetOne(ctx, pollID, &p); err != nil { + return group.Poll{}, sdkerrors.Wrap(err, "load poll") + } + return p, nil +} + +func (s serverImpl) PollsByGroup(goCtx context.Context, request *group.QueryPollsByGroupRequest) (*group.QueryPollsByGroupResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + groupID := request.GroupId + it, err := s.getPollsByGroup(ctx, groupID, request.Pagination) + if err != nil { + return nil, err + } + + var polls []*group.Poll + pageRes, err := orm.Paginate(it, request.Pagination, &polls) + if err != nil { + return nil, err + } + + return &group.QueryPollsByGroupResponse{ + Polls: polls, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getPollsByGroup(ctx types.Context, id uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.pollByGroupIndex.GetPaginated(ctx, id, pageRequest) +} + +func (s serverImpl) PollsByCreator(goCtx context.Context, request *group.QueryPollsByCreatorRequest) (*group.QueryPollsByCreatorResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Creator) + if err != nil { + return nil, err + } + it, err := s.getPollsByCreator(ctx, addr, request.Pagination) + if err != nil { + return nil, err + } + + var polls []*group.Poll + pageRes, err := orm.Paginate(it, request.Pagination, &polls) + if err != nil { + return nil, err + } + + return &group.QueryPollsByCreatorResponse{ + Polls: polls, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getPollsByCreator(ctx types.Context, account sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.pollByCreatorIndex.GetPaginated(ctx, account.Bytes(), pageRequest) +} + +func (s serverImpl) VoteForPollByPollVoter(goCtx context.Context, request *group.QueryVoteForPollByPollVoterRequest) (*group.QueryVoteForPollByPollVoterResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Voter) + if err != nil { + return nil, err + } + pollID := request.PollId + vote, err := s.getVoteForPoll(ctx, pollID, addr) + if err != nil { + return nil, err + } + return &group.QueryVoteForPollByPollVoterResponse{ + Vote: &vote, + }, nil +} + +func (s serverImpl) VotesForPollByPoll(goCtx context.Context, request *group.QueryVotesForPollByPollRequest) (*group.QueryVotesForPollByPollResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + pollID := request.PollId + it, err := s.getVotesForPollByPoll(ctx, pollID, request.Pagination) + if err != nil { + return nil, err + } + + var votes []*group.VotePoll + pageRes, err := orm.Paginate(it, request.Pagination, &votes) + if err != nil { + return nil, err + } + + return &group.QueryVotesForPollByPollResponse{ + Votes: votes, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) VotesForPollByVoter(goCtx context.Context, request *group.QueryVotesForPollByVoterRequest) (*group.QueryVotesForPollByVoterResponse, error) { + ctx := types.UnwrapSDKContext(goCtx) + addr, err := sdk.AccAddressFromBech32(request.Voter) + if err != nil { + return nil, err + } + it, err := s.getVotesForPollByVoter(ctx, addr, request.Pagination) + if err != nil { + return nil, err + } + + var votes []*group.VotePoll + pageRes, err := orm.Paginate(it, request.Pagination, &votes) + if err != nil { + return nil, err + } + + return &group.QueryVotesForPollByVoterResponse{ + Votes: votes, + Pagination: pageRes, + }, nil +} + +func (s serverImpl) getVoteForPoll(ctx types.Context, pollID uint64, voter sdk.AccAddress) (group.VotePoll, error) { + var v group.VotePoll + return v, s.votePollTable.GetOne(ctx, orm.PrimaryKey(&group.VotePoll{PollId: pollID, Voter: voter.String()}), &v) +} + +func (s serverImpl) getVotesForPollByPoll(ctx types.Context, pollID uint64, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.votePollByPollIndex.GetPaginated(ctx, pollID, pageRequest) +} + +func (s serverImpl) getVotesForPollByVoter(ctx types.Context, voter sdk.AccAddress, pageRequest *query.PageRequest) (orm.Iterator, error) { + return s.votePollByVoterIndex.GetPaginated(ctx, voter.Bytes(), pageRequest) +} \ No newline at end of file diff --git a/x/group/server/server.go b/x/group/server/server.go new file mode 100644 index 0000000000..5c38385f22 --- /dev/null +++ b/x/group/server/server.go @@ -0,0 +1,220 @@ +package server + +import ( + "github.com/cosmos/cosmos-sdk/regen/orm" + servermodule "github.com/cosmos/cosmos-sdk/regen/types/module/server" + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/exported" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const ( + // Group Table + GroupTablePrefix byte = 0x0 + GroupTableSeqPrefix byte = 0x1 + GroupByAdminIndexPrefix byte = 0x2 + + // Group Member Table + GroupMemberTablePrefix byte = 0x10 + GroupMemberByGroupIndexPrefix byte = 0x11 + GroupMemberByMemberIndexPrefix byte = 0x12 + + // Group Account Table + GroupAccountTablePrefix byte = 0x20 + GroupAccountTableSeqPrefix byte = 0x21 + GroupAccountByGroupIndexPrefix byte = 0x22 + GroupAccountByAdminIndexPrefix byte = 0x23 + + // Proposal Table + ProposalTablePrefix byte = 0x30 + ProposalTableSeqPrefix byte = 0x31 + ProposalByGroupAccountIndexPrefix byte = 0x32 + ProposalByProposerIndexPrefix byte = 0x33 + + // Vote Table + VoteTablePrefix byte = 0x40 + VoteByProposalIndexPrefix byte = 0x41 + VoteByVoterIndexPrefix byte = 0x42 + + // Poll Table + PollTablePrefix byte = 0x90 + PollTableSeqPrefix byte = 0x91 + PollByGroupIndexPrefix byte = 0x92 + PollByCreatorIndexPrefix byte = 0x93 + + // VotePoll Table + VotePollTablePrefix byte = 0xa0 + VotePollByPollIndexPrefix byte = 0xa1 + VotePollByVoterIndexPrefix byte = 0xa2 +) + +type serverImpl struct { + key servermodule.RootModuleKey + + accKeeper exported.AccountKeeper + bankKeeper exported.BankKeeper + + // Group Table + groupTable orm.AutoUInt64Table + groupByAdminIndex orm.Index + + // Group Member Table + groupMemberTable orm.PrimaryKeyTable + groupMemberByGroupIndex orm.UInt64Index + groupMemberByMemberIndex orm.Index + + // Group Account Table + groupAccountSeq orm.Sequence + groupAccountTable orm.PrimaryKeyTable + groupAccountByGroupIndex orm.UInt64Index + groupAccountByAdminIndex orm.Index + + // Proposal Table + proposalTable orm.AutoUInt64Table + proposalByGroupAccountIndex orm.Index + proposalByProposerIndex orm.Index + + // Vote Table + voteTable orm.PrimaryKeyTable + voteByProposalIndex orm.UInt64Index + voteByVoterIndex orm.Index + + // Poll Table + pollTable orm.AutoUInt64Table + pollByGroupIndex orm.UInt64Index + pollByCreatorIndex orm.Index + + // VotePoll Table + votePollTable orm.PrimaryKeyTable + votePollByPollIndex orm.UInt64Index + votePollByVoterIndex orm.Index +} + +func newServer(storeKey servermodule.RootModuleKey, accKeeper exported.AccountKeeper, bankKeeper exported.BankKeeper, cdc codec.Codec) serverImpl { + s := serverImpl{key: storeKey, accKeeper: accKeeper, bankKeeper: bankKeeper} + + // Group Table + groupTableBuilder := orm.NewAutoUInt64TableBuilder(GroupTablePrefix, GroupTableSeqPrefix, storeKey, &group.GroupInfo{}, cdc) + s.groupByAdminIndex = orm.NewIndex(groupTableBuilder, GroupByAdminIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + addr, err := sdk.AccAddressFromBech32(val.(*group.GroupInfo).Admin) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.groupTable = groupTableBuilder.Build() + + // Group Member Table + groupMemberTableBuilder := orm.NewPrimaryKeyTableBuilder(GroupMemberTablePrefix, storeKey, &group.GroupMember{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + s.groupMemberByGroupIndex = orm.NewUInt64Index(groupMemberTableBuilder, GroupMemberByGroupIndexPrefix, func(val interface{}) ([]uint64, error) { + group := val.(*group.GroupMember).GroupId + return []uint64{group}, nil + }) + s.groupMemberByMemberIndex = orm.NewIndex(groupMemberTableBuilder, GroupMemberByMemberIndexPrefix, func(val interface{}) ([]orm.RowID, error) { + memberAddr := val.(*group.GroupMember).Member.Address + addr, err := sdk.AccAddressFromBech32(memberAddr) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.groupMemberTable = groupMemberTableBuilder.Build() + + // Group Account Table + s.groupAccountSeq = orm.NewSequence(storeKey, GroupAccountTableSeqPrefix) + groupAccountTableBuilder := orm.NewPrimaryKeyTableBuilder(GroupAccountTablePrefix, storeKey, &group.GroupAccountInfo{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + s.groupAccountByGroupIndex = orm.NewUInt64Index(groupAccountTableBuilder, GroupAccountByGroupIndexPrefix, func(value interface{}) ([]uint64, error) { + group := value.(*group.GroupAccountInfo).GroupId + return []uint64{group}, nil + }) + s.groupAccountByAdminIndex = orm.NewIndex(groupAccountTableBuilder, GroupAccountByAdminIndexPrefix, func(value interface{}) ([]orm.RowID, error) { + admin := value.(*group.GroupAccountInfo).Admin + addr, err := sdk.AccAddressFromBech32(admin) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.groupAccountTable = groupAccountTableBuilder.Build() + + // Proposal Table + proposalTableBuilder := orm.NewAutoUInt64TableBuilder(ProposalTablePrefix, ProposalTableSeqPrefix, storeKey, &group.Proposal{}, cdc) + s.proposalByGroupAccountIndex = orm.NewIndex(proposalTableBuilder, ProposalByGroupAccountIndexPrefix, func(value interface{}) ([]orm.RowID, error) { + account := value.(*group.Proposal).Address + addr, err := sdk.AccAddressFromBech32(account) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.proposalByProposerIndex = orm.NewIndex(proposalTableBuilder, ProposalByProposerIndexPrefix, func(value interface{}) ([]orm.RowID, error) { + proposers := value.(*group.Proposal).Proposers + r := make([]orm.RowID, len(proposers)) + for i := range proposers { + addr, err := sdk.AccAddressFromBech32(proposers[i]) + if err != nil { + return nil, err + } + r[i] = addr.Bytes() + } + return r, nil + }) + s.proposalTable = proposalTableBuilder.Build() + + // Vote Table + voteTableBuilder := orm.NewPrimaryKeyTableBuilder(VoteTablePrefix, storeKey, &group.Vote{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + s.voteByProposalIndex = orm.NewUInt64Index(voteTableBuilder, VoteByProposalIndexPrefix, func(value interface{}) ([]uint64, error) { + return []uint64{value.(*group.Vote).ProposalId}, nil + }) + s.voteByVoterIndex = orm.NewIndex(voteTableBuilder, VoteByVoterIndexPrefix, func(value interface{}) ([]orm.RowID, error) { + addr, err := sdk.AccAddressFromBech32(value.(*group.Vote).Voter) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.voteTable = voteTableBuilder.Build() + + // Poll Table + pollTableBuilder := orm.NewAutoUInt64TableBuilder(PollTablePrefix, PollTableSeqPrefix, storeKey, &group.Poll{}, cdc) + s.pollByGroupIndex = orm.NewUInt64Index(pollTableBuilder, PollByGroupIndexPrefix, func(value interface{}) ([]uint64, error) { + group := value.(*group.Poll).GroupId + return []uint64{group}, nil + }) + s.pollByCreatorIndex = orm.NewIndex(pollTableBuilder, PollByCreatorIndexPrefix, func(value interface{}) ([]orm.RowID, error) { + creator := value.(*group.Poll).Creator + addr, err := sdk.AccAddressFromBech32(creator) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.pollTable = pollTableBuilder.Build() + + // VotePoll Table + votePollTableBuilder := orm.NewPrimaryKeyTableBuilder(VotePollTablePrefix, storeKey, &group.VotePoll{}, orm.Max255DynamicLengthIndexKeyCodec{}, cdc) + s.votePollByPollIndex = orm.NewUInt64Index(votePollTableBuilder, VotePollByPollIndexPrefix, func(value interface{}) ([]uint64, error) { + return []uint64{value.(*group.VotePoll).PollId}, nil + }) + s.votePollByVoterIndex = orm.NewIndex(votePollTableBuilder, VotePollByVoterIndexPrefix, func(value interface{}) ([]orm.RowID, error) { + addr, err := sdk.AccAddressFromBech32(value.(*group.VotePoll).Voter) + if err != nil { + return nil, err + } + return []orm.RowID{addr.Bytes()}, nil + }) + s.votePollTable = votePollTableBuilder.Build() + + return s +} + +func RegisterServices(configurator servermodule.Configurator, accountKeeper exported.AccountKeeper, bankKeeper exported.BankKeeper) { + impl := newServer(configurator.ModuleKey(), accountKeeper, bankKeeper, configurator.Marshaler()) + group.RegisterMsgServer(configurator.MsgServer(), impl) + group.RegisterQueryServer(configurator.QueryServer(), impl) + configurator.RegisterInvariantsHandler(impl.RegisterInvariants) + configurator.RegisterGenesisHandlers(impl.InitGenesis, impl.ExportGenesis) + configurator.RegisterWeightedOperationsHandler(impl.WeightedOperations) +} diff --git a/x/group/server/server_test.go b/x/group/server/server_test.go new file mode 100644 index 0000000000..d5999373fc --- /dev/null +++ b/x/group/server/server_test.go @@ -0,0 +1,88 @@ +package server_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/regen/types/module" + "github.com/cosmos/cosmos-sdk/regen/types/module/server" + groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" + "github.com/cosmos/cosmos-sdk/x/group/server/testsuite" +) + +func TestServer(t *testing.T) { + ff := server.NewFixtureFactory(t, 6) + cdc := ff.Codec() + // Setting up bank keeper + banktypes.RegisterInterfaces(cdc.InterfaceRegistry()) + authtypes.RegisterInterfaces(cdc.InterfaceRegistry()) + + paramsKey := sdk.NewKVStoreKey(paramstypes.StoreKey) + authKey := sdk.NewKVStoreKey(authtypes.StoreKey) + bankKey := sdk.NewKVStoreKey(banktypes.StoreKey) + mintKey := sdk.NewKVStoreKey(minttypes.StoreKey) + stakingKey := sdk.NewKVStoreKey(stakingtypes.StoreKey) + tkey := sdk.NewTransientStoreKey(paramstypes.TStoreKey) + amino := codec.NewLegacyAmino() + + authSubspace := paramstypes.NewSubspace(cdc, amino, paramsKey, tkey, authtypes.ModuleName) + bankSubspace := paramstypes.NewSubspace(cdc, amino, paramsKey, tkey, banktypes.ModuleName) + stakingSubspace := paramstypes.NewSubspace(cdc, amino, paramsKey, tkey, stakingtypes.ModuleName) + mintSubspace := paramstypes.NewSubspace(cdc, amino, paramsKey, tkey, minttypes.ModuleName) + + maccPerms := map[string][]string{ + authtypes.FeeCollectorName: nil, + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + } + + accountKeeper := authkeeper.NewAccountKeeper( + cdc, authKey, authSubspace, authtypes.ProtoBaseAccount, maccPerms, + ) + + modAccAddrs := make(map[string]bool) + for acc := range maccPerms { + modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true + } + + bankKeeper := bankkeeper.NewBaseKeeper( + cdc, bankKey, accountKeeper, bankSubspace, modAccAddrs, + ) + + stakingKeeper := stakingkeeper.NewKeeper( + cdc, stakingKey, accountKeeper, bankKeeper, stakingSubspace, + ) + + mintKeeper := mintkeeper.NewKeeper( + cdc, mintKey, mintSubspace, stakingKeeper, accountKeeper, bankKeeper, authtypes.FeeCollectorName, + ) + + baseApp := ff.BaseApp() + baseApp.MsgServiceRouter().SetInterfaceRegistry(cdc.InterfaceRegistry()) + banktypes.RegisterMsgServer(baseApp.MsgServiceRouter(), bankkeeper.NewMsgServerImpl(bankKeeper)) + baseApp.MountStore(tkey, sdk.StoreTypeTransient) + baseApp.MountStore(paramsKey, sdk.StoreTypeIAVL) + baseApp.MountStore(authKey, sdk.StoreTypeIAVL) + baseApp.MountStore(bankKey, sdk.StoreTypeIAVL) + baseApp.MountStore(stakingKey, sdk.StoreTypeIAVL) + baseApp.MountStore(mintKey, sdk.StoreTypeIAVL) + + ff.SetModules([]module.Module{groupmodule.Module{AccountKeeper: accountKeeper}}) + + s := testsuite.NewIntegrationTestSuite(ff, accountKeeper, bankKeeper, mintKeeper) + + suite.Run(t, s) +} diff --git a/x/group/server/testsuite/genesis.go b/x/group/server/testsuite/genesis.go new file mode 100644 index 0000000000..00e27133aa --- /dev/null +++ b/x/group/server/testsuite/genesis.go @@ -0,0 +1,178 @@ +package testsuite + +import ( + "encoding/json" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/group" + proto "github.com/gogo/protobuf/types" +) + +func (s *IntegrationTestSuite) TestInitExportGenesis() { + require := s.Require() + ctx := s.genesisCtx + cdc := s.fixture.Codec() + + now := time.Now() + submittedAt, err := proto.TimestampProto(now) + require.NoError(err) + timeout, err := proto.TimestampProto(now.Add(time.Second * 1)) + require.NoError(err) + + groupAccount := &group.GroupAccountInfo{ + Address: s.groupAccountAddr.String(), + GroupId: 1, + Admin: s.addr1.String(), + Version: 1, + Metadata: []byte("account metadata"), + DerivationKey: []byte("account derivation key"), + } + err = groupAccount.SetDecisionPolicy(&group.ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }) + require.NoError(err) + + proposal := &group.Proposal{ + ProposalId: 1, + Address: s.groupAccountAddr.String(), + Metadata: []byte("proposal metadata"), + GroupVersion: 1, + GroupAccountVersion: 1, + Proposers: []string{ + s.addr1.String(), + }, + SubmittedAt: *submittedAt, + Status: group.ProposalStatusClosed, + Result: group.ProposalResultAccepted, + VoteState: group.Tally{ + YesCount: "1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + Timeout: *timeout, + ExecutorResult: group.ProposalExecutorResultSuccess, + } + err = proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ + FromAddress: s.groupAccountAddr.String(), + ToAddress: s.addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + }}) + require.NoError(err) + + genesisState := &group.GenesisState{ + GroupSeq: 2, + Groups: []*group.GroupInfo{{GroupId: 1, Admin: s.addr1.String(), Metadata: []byte("1"), Version: 1, TotalWeight: "1"}, {GroupId: 2, Admin: s.addr2.String(), Metadata: []byte("2"), Version: 2, TotalWeight: "2"}}, + GroupMembers: []*group.GroupMember{{GroupId: 1, Member: &group.Member{Address: s.addr1.String(), Weight: "1", Metadata: []byte("member metadata")}}, {GroupId: 2, Member: &group.Member{Address: s.addr1.String(), Weight: "2", Metadata: []byte("member metadata")}}}, + GroupAccountSeq: 1, + GroupAccounts: []*group.GroupAccountInfo{groupAccount}, + ProposalSeq: 1, + Proposals: []*group.Proposal{proposal}, + Votes: []*group.Vote{{ProposalId: proposal.ProposalId, Voter: s.addr1.String(), SubmittedAt: *submittedAt, Choice: group.Choice_CHOICE_YES}}, + } + + genesisBytes, err := cdc.MarshalJSON(genesisState) + require.NoError(err) + + genesisData := map[string]json.RawMessage{group.ModuleName: genesisBytes} + _, err = s.fixture.InitGenesis(ctx.Context, genesisData) + require.NoError(err) + + for i, g := range genesisState.Groups { + res, err := s.queryClient.GroupInfo(ctx, &group.QueryGroupInfoRequest{ + GroupId: g.GroupId, + }) + require.NoError(err) + require.Equal(g, res.Info) + + membersRes, err := s.queryClient.GroupMembers(ctx, &group.QueryGroupMembersRequest{ + GroupId: g.GroupId, + }) + require.NoError(err) + require.Equal(len(membersRes.Members), 1) + require.Equal(membersRes.Members[0], genesisState.GroupMembers[i]) + } + + for _, g := range genesisState.GroupAccounts { + res, err := s.queryClient.GroupAccountInfo(ctx, &group.QueryGroupAccountInfoRequest{ + Address: g.Address, + }) + require.NoError(err) + s.assertGroupAccountsEqual(g, res.Info) + } + + for _, g := range genesisState.Proposals { + res, err := s.queryClient.Proposal(ctx, &group.QueryProposalRequest{ + ProposalId: g.ProposalId, + }) + require.NoError(err) + s.assertProposalsEqual(g, res.Proposal) + + votesRes, err := s.queryClient.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ + ProposalId: g.ProposalId, + }) + require.NoError(err) + require.Equal(len(votesRes.Votes), 1) + require.Equal(votesRes.Votes[0], genesisState.Votes[0]) + } + + exported, err := s.fixture.ExportGenesis(ctx.Context) + require.NoError(err) + + var exportedGenesisState group.GenesisState + err = cdc.UnmarshalJSON(exported[group.ModuleName], &exportedGenesisState) + require.NoError(err) + + require.Equal(genesisState.Groups, exportedGenesisState.Groups) + require.Equal(genesisState.GroupMembers, exportedGenesisState.GroupMembers) + + require.Equal(len(genesisState.GroupAccounts), len(exportedGenesisState.GroupAccounts)) + for i, g := range genesisState.GroupAccounts { + res := exportedGenesisState.GroupAccounts[i] + require.NoError(err) + s.assertGroupAccountsEqual(g, res) + } + + require.Equal(len(genesisState.Proposals), len(exportedGenesisState.Proposals)) + for i, g := range genesisState.Proposals { + res := exportedGenesisState.Proposals[i] + require.NoError(err) + s.assertProposalsEqual(g, res) + } + require.Equal(genesisState.Votes, exportedGenesisState.Votes) + + require.Equal(genesisState.GroupSeq, exportedGenesisState.GroupSeq) + require.Equal(genesisState.GroupAccountSeq, exportedGenesisState.GroupAccountSeq) + require.Equal(genesisState.ProposalSeq, exportedGenesisState.ProposalSeq) + +} + +func (s *IntegrationTestSuite) assertGroupAccountsEqual(g *group.GroupAccountInfo, other *group.GroupAccountInfo) { + require := s.Require() + require.Equal(g.Address, other.Address) + require.Equal(g.GroupId, other.GroupId) + require.Equal(g.Admin, other.Admin) + require.Equal(g.Metadata, other.Metadata) + require.Equal(g.Version, other.Version) + require.Equal(g.GetDecisionPolicy(), other.GetDecisionPolicy()) +} + +func (s *IntegrationTestSuite) assertProposalsEqual(g *group.Proposal, other *group.Proposal) { + require := s.Require() + require.Equal(g.ProposalId, other.ProposalId) + require.Equal(g.Address, other.Address) + require.Equal(g.Metadata, other.Metadata) + require.Equal(g.Proposers, other.Proposers) + require.Equal(g.SubmittedAt, other.SubmittedAt) + require.Equal(g.GroupVersion, other.GroupVersion) + require.Equal(g.GroupAccountVersion, other.GroupAccountVersion) + require.Equal(g.Status, other.Status) + require.Equal(g.Result, other.Result) + require.Equal(g.VoteState, other.VoteState) + require.Equal(g.Timeout, other.Timeout) + require.Equal(g.ExecutorResult, other.ExecutorResult) + require.Equal(g.GetMsgs(), other.GetMsgs()) +} diff --git a/x/group/server/testsuite/suite.go b/x/group/server/testsuite/suite.go new file mode 100644 index 0000000000..31d582f140 --- /dev/null +++ b/x/group/server/testsuite/suite.go @@ -0,0 +1,3410 @@ +package testsuite + +import ( + "context" + "fmt" + + "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + + //"github.com/cosmos/cosmos-sdk/x/group/server" + + //"github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + "sort" + "strings" + "time" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/cosmos/cosmos-sdk/x/group/testdata" + + sdk "github.com/cosmos/cosmos-sdk/types" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + + gogotypes "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/suite" + + "github.com/cosmos/cosmos-sdk/regen/types" + servermodule "github.com/cosmos/cosmos-sdk/regen/types/module/server" + "github.com/cosmos/cosmos-sdk/regen/types/testutil" + "github.com/cosmos/cosmos-sdk/x/group" +) + +type IntegrationTestSuite struct { + suite.Suite + + fixtureFactory *servermodule.FixtureFactory + fixture testutil.Fixture + + ctx context.Context + sdkCtx sdk.Context + genesisCtx types.Context + msgClient group.MsgClient + queryClient group.QueryClient + addr1 sdk.AccAddress + addr2 sdk.AccAddress + addr3 sdk.AccAddress + addr4 sdk.AccAddress + addr5 sdk.AccAddress + addr6 sdk.AccAddress + addrBls1 sdk.AccAddress + addrBls2 sdk.AccAddress + addrBls3 sdk.AccAddress + addrBls4 sdk.AccAddress + addrBls5 sdk.AccAddress + addrBls6 sdk.AccAddress + groupAccountAddr sdk.AccAddress + groupID uint64 + + skBls1 cryptotypes.PrivKey + skBls2 cryptotypes.PrivKey + skBls3 cryptotypes.PrivKey + skBls4 cryptotypes.PrivKey + skBls5 cryptotypes.PrivKey + skBls6 cryptotypes.PrivKey + + accountKeeper authkeeper.AccountKeeper + // paramSpace paramstypes.Subspace + bankKeeper bankkeeper.Keeper + mintKeeper mintkeeper.Keeper + + blockTime time.Time +} + +func NewIntegrationTestSuite( + fixtureFactory *servermodule.FixtureFactory, + accountKeeper authkeeper.AccountKeeper, + bankKeeper bankkeeper.BaseKeeper, + mintKeeper mintkeeper.Keeper, + //paramSpace paramstypes.Subspace +) *IntegrationTestSuite { + + return &IntegrationTestSuite{ + fixtureFactory: fixtureFactory, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + mintKeeper: mintKeeper, + // paramSpace: paramSpace, + } +} + +func (s *IntegrationTestSuite) SetupSuite() { + s.fixture = s.fixtureFactory.Setup() + + s.blockTime = time.Now().UTC() + + // TODO clean up once types.Context merged upstream into sdk.Context + sdkCtx := s.fixture.Context().(types.Context).WithBlockTime(s.blockTime) + s.sdkCtx, _ = sdkCtx.CacheContext() + s.ctx = types.Context{Context: s.sdkCtx} + s.genesisCtx = types.Context{Context: sdkCtx} + s.Require().NoError(s.bankKeeper.MintCoins(s.sdkCtx, minttypes.ModuleName, sdk.NewCoins(sdk.NewInt64Coin("test", 400000000)))) + + s.accountKeeper.SetParams(sdkCtx, authtypes.DefaultParams()) + s.bankKeeper.SetParams(sdkCtx, banktypes.DefaultParams()) + + s.msgClient = group.NewMsgClient(s.fixture.TxConn()) + s.queryClient = group.NewQueryClient(s.fixture.QueryConn()) + + s.Require().GreaterOrEqual(len(s.fixture.Signers()), 6) + s.addr1 = s.fixture.Signers()[0] + s.addr2 = s.fixture.Signers()[1] + s.addr3 = s.fixture.Signers()[2] + s.addr4 = s.fixture.Signers()[3] + s.addr5 = s.fixture.Signers()[4] + s.addr6 = s.fixture.Signers()[5] + + s.addrBls1 = s.fixture.SignersBls()[0] + s.addrBls2 = s.fixture.SignersBls()[1] + s.addrBls3 = s.fixture.SignersBls()[2] + s.addrBls4 = s.fixture.SignersBls()[3] + s.addrBls5 = s.fixture.SignersBls()[4] + s.addrBls6 = s.fixture.SignersBls()[5] + + s.skBls1 = s.fixture.SksBls()[0] + s.skBls2 = s.fixture.SksBls()[1] + s.skBls3 = s.fixture.SksBls()[2] + s.skBls4 = s.fixture.SksBls()[3] + s.skBls5 = s.fixture.SksBls()[4] + s.skBls6 = s.fixture.SksBls()[5] + + accBls1 := s.accountKeeper.NewAccountWithAddress(s.sdkCtx, s.addrBls1) + accBls2 := s.accountKeeper.NewAccountWithAddress(s.sdkCtx, s.addrBls2) + accBls3 := s.accountKeeper.NewAccountWithAddress(s.sdkCtx, s.addrBls3) + accBls4 := s.accountKeeper.NewAccountWithAddress(s.sdkCtx, s.addrBls4) + accBls5 := s.accountKeeper.NewAccountWithAddress(s.sdkCtx, s.addrBls5) + accBls6 := s.accountKeeper.NewAccountWithAddress(s.sdkCtx, s.addrBls6) + + pkBls1 := s.skBls1.PubKey() + pkBls2 := s.skBls2.PubKey() + pkBls3 := s.skBls3.PubKey() + pkBls4 := s.skBls4.PubKey() + pkBls5 := s.skBls5.PubKey() + pkBls6 := s.skBls6.PubKey() + + err := accBls1.SetPubKey(pkBls1) + s.Require().NoError(err) + err = accBls2.SetPubKey(pkBls2) + s.Require().NoError(err) + err = accBls3.SetPubKey(pkBls3) + s.Require().NoError(err) + err = accBls4.SetPubKey(pkBls4) + s.Require().NoError(err) + err = accBls5.SetPubKey(pkBls5) + s.Require().NoError(err) + err = accBls6.SetPubKey(pkBls6) + s.Require().NoError(err) + + err = accBls1.SetPopValid(true) + s.Require().NoError(err) + err = accBls2.SetPopValid(true) + s.Require().NoError(err) + err = accBls3.SetPopValid(true) + s.Require().NoError(err) + err = accBls4.SetPopValid(true) + s.Require().NoError(err) + err = accBls5.SetPopValid(true) + s.Require().NoError(err) + err = accBls6.SetPopValid(true) + s.Require().NoError(err) + + s.accountKeeper.SetAccount(s.sdkCtx, accBls1) + s.accountKeeper.SetAccount(s.sdkCtx, accBls2) + s.accountKeeper.SetAccount(s.sdkCtx, accBls3) + s.accountKeeper.SetAccount(s.sdkCtx, accBls4) + s.accountKeeper.SetAccount(s.sdkCtx, accBls5) + s.accountKeeper.SetAccount(s.sdkCtx, accBls6) + + // Initial group, group account and balance setup + members := []group.Member{ + {Address: s.addr5.String(), Weight: "1"}, {Address: s.addr2.String(), Weight: "2"}, + } + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: members, + Metadata: nil, + }) + s.Require().NoError(err) + s.groupID = groupRes.GroupId + + policy := group.NewThresholdDecisionPolicy( + "2", + gogotypes.Duration{Seconds: 1}, + ) + accountReq := &group.MsgCreateGroupAccount{ + Admin: s.addr1.String(), + GroupId: s.groupID, + Metadata: nil, + } + err = accountReq.SetDecisionPolicy(policy) + s.Require().NoError(err) + accountRes, err := s.msgClient.CreateGroupAccount(s.ctx, accountReq) + s.Require().NoError(err) + addr, err := sdk.AccAddressFromBech32(accountRes.Address) + s.Require().NoError(err) + s.groupAccountAddr = addr + s.Require().NoError(fundAccount(s.bankKeeper, s.sdkCtx, s.groupAccountAddr, sdk.Coins{sdk.NewInt64Coin("test", 10000)})) +} + +func (s *IntegrationTestSuite) TearDownSuite() { + s.fixture.Teardown() +} + +// TODO: https://github.com/cosmos/cosmos-sdk/issues/9346 +func fundAccount(bankKeeper bankkeeper.Keeper, ctx sdk.Context, addr sdk.AccAddress, amounts sdk.Coins) error { + if err := bankKeeper.MintCoins(ctx, minttypes.ModuleName, amounts); err != nil { + return err + } + return bankKeeper.SendCoinsFromModuleToAccount(ctx, minttypes.ModuleName, addr, amounts) +} + +func (s *IntegrationTestSuite) TestCreateGroup() { + members := []group.Member{{ + Address: s.addr5.String(), + Weight: "1", + Metadata: nil, + }, { + Address: s.addr6.String(), + Weight: "2", + Metadata: nil, + }} + + blsMembers := []group.Member{{ + Address: s.addrBls1.String(), + Weight: "3", + Metadata: nil, + }, { + Address: s.addrBls2.String(), + Weight: "5", + Metadata: nil, + }} + + mixedMembers := []group.Member{{ + Address: s.addr5.String(), + Weight: "2", + Metadata: nil, + }, { + Address: s.addrBls1.String(), + Weight: "3", + Metadata: nil, + }} + + expGroups := []*group.GroupInfo{ + { + GroupId: s.groupID, + Version: 1, + Admin: s.addr1.String(), + TotalWeight: "3", + Metadata: nil, + }, + { + GroupId: 2, + Version: 1, + Admin: s.addr1.String(), + TotalWeight: "3", + Metadata: nil, + }, + { + GroupId: 2, + Version: 1, + Admin: s.addr1.String(), + TotalWeight: "8", + Metadata: nil, + BlsOnly: true, + }, + { + GroupId: 2, + Version: 1, + Admin: s.addr1.String(), + TotalWeight: "5", + Metadata: nil, + }, + } + + specs := map[string]struct { + req *group.MsgCreateGroup + expErr bool + expGroups []*group.GroupInfo + mems []group.Member + }{ + "all good": { + req: &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: members, + Metadata: nil, + }, + expGroups: expGroups[0:2], + mems: members, + }, + "all good with bls members": { + req: &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: blsMembers, + Metadata: nil, + BlsOnly: true, + }, + expGroups: []*group.GroupInfo{ + expGroups[0], + expGroups[2], + }, + mems: blsMembers, + }, + "all good with mixed members": { + req: &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: mixedMembers, + Metadata: nil, + BlsOnly: false, + }, + expGroups: []*group.GroupInfo{ + expGroups[0], + expGroups[3], + }, + mems: mixedMembers, + }, + "mixed members not allowed when bls only": { + req: &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: mixedMembers, + Metadata: nil, + BlsOnly: true, + }, + expErr: true, + mems: mixedMembers, + }, + "zero member weight": { + req: &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: []group.Member{{ + Address: s.addr3.String(), + Weight: "0", + Metadata: nil, + }}, + Metadata: nil, + }, + expErr: true, + }, + } + + var seq uint32 = 1 + for msg, spec := range specs { + s.Run(msg, func() { + sdkCtx, _ := s.sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + + res, err := s.msgClient.CreateGroup(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + _, err := s.queryClient.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: uint64(seq + 1)}) + s.Require().Error(err) + return + } + s.Require().NoError(err) + id := res.GroupId + + s.Assert().Equal(uint64(2), id) + + // then all data persisted + loadedGroupRes, err := s.queryClient.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: id}) + s.Require().NoError(err) + s.Assert().Equal(spec.req.Admin, loadedGroupRes.Info.Admin) + s.Assert().Equal(spec.req.Metadata, loadedGroupRes.Info.Metadata) + s.Assert().Equal(id, loadedGroupRes.Info.GroupId) + s.Assert().Equal(uint64(1), loadedGroupRes.Info.Version) + + // and members are stored as well + membersRes, err := s.queryClient.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: id}) + s.Require().NoError(err) + loadedMembers := membersRes.Members + s.Require().Equal(len(spec.mems), len(loadedMembers)) + // we reorder members by address to be able to compare them + sort.Slice(spec.mems, func(i, j int) bool { return spec.mems[i].Address < spec.mems[j].Address }) + for i := range loadedMembers { + s.Assert().Equal(spec.mems[i].Metadata, loadedMembers[i].Member.Metadata) + s.Assert().Equal(spec.mems[i].Address, loadedMembers[i].Member.Address) + s.Assert().Equal(spec.mems[i].Weight, loadedMembers[i].Member.Weight) + s.Assert().Equal(id, loadedMembers[i].GroupId) + } + + // query groups by admin + groupsRes, err := s.queryClient.GroupsByAdmin(ctx, &group.QueryGroupsByAdminRequest{Admin: s.addr1.String()}) + s.Require().NoError(err) + loadedGroups := groupsRes.Groups + s.Require().Equal(len(spec.expGroups), len(loadedGroups)) + for i := range loadedGroups { + s.Assert().Equal(spec.expGroups[i].Metadata, loadedGroups[i].Metadata) + s.Assert().Equal(spec.expGroups[i].Admin, loadedGroups[i].Admin) + s.Assert().Equal(spec.expGroups[i].TotalWeight, loadedGroups[i].TotalWeight) + s.Assert().Equal(spec.expGroups[i].GroupId, loadedGroups[i].GroupId) + s.Assert().Equal(spec.expGroups[i].Version, loadedGroups[i].Version) + s.Assert().Equal(spec.expGroups[i].BlsOnly, loadedGroups[i].BlsOnly) + } + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupAdmin() { + members := []group.Member{{ + Address: s.addr1.String(), + Weight: "1", + Metadata: nil, + }} + oldAdmin := s.addr2.String() + newAdmin := s.addr3.String() + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: oldAdmin, + Members: members, + Metadata: nil, + }) + s.Require().NoError(err) + groupID := groupRes.GroupId + + specs := map[string]struct { + req *group.MsgUpdateGroupAdmin + expStored *group.GroupInfo + expErr bool + }{ + "with correct admin": { + req: &group.MsgUpdateGroupAdmin{ + GroupId: groupID, + Admin: oldAdmin, + NewAdmin: newAdmin, + }, + expStored: &group.GroupInfo{ + GroupId: groupID, + Admin: newAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 2, + }, + }, + "with wrong admin": { + req: &group.MsgUpdateGroupAdmin{ + GroupId: groupID, + Admin: s.addr4.String(), + NewAdmin: newAdmin, + }, + expErr: true, + expStored: &group.GroupInfo{ + GroupId: groupID, + Admin: oldAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + }, + "with unknown groupID": { + req: &group.MsgUpdateGroupAdmin{ + GroupId: 999, + Admin: oldAdmin, + NewAdmin: newAdmin, + }, + expErr: true, + expStored: &group.GroupInfo{ + GroupId: groupID, + Admin: oldAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + _, err := s.msgClient.UpdateGroupAdmin(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // then + res, err := s.queryClient.GroupInfo(s.ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) + s.Require().NoError(err) + s.Assert().Equal(spec.expStored, res.Info) + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupMetadata() { + oldAdmin := s.addr1.String() + groupID := s.groupID + + specs := map[string]struct { + req *group.MsgUpdateGroupMetadata + expErr bool + expStored *group.GroupInfo + }{ + "with correct admin": { + req: &group.MsgUpdateGroupMetadata{ + GroupId: groupID, + Admin: oldAdmin, + Metadata: []byte{1, 2, 3}, + }, + expStored: &group.GroupInfo{ + GroupId: groupID, + Admin: oldAdmin, + Metadata: []byte{1, 2, 3}, + TotalWeight: "3", + Version: 2, + }, + }, + "with wrong admin": { + req: &group.MsgUpdateGroupMetadata{ + GroupId: groupID, + Admin: s.addr3.String(), + Metadata: []byte{1, 2, 3}, + }, + expErr: true, + expStored: &group.GroupInfo{ + GroupId: groupID, + Admin: oldAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + }, + "with unknown groupid": { + req: &group.MsgUpdateGroupMetadata{ + GroupId: 999, + Admin: oldAdmin, + Metadata: []byte{1, 2, 3}, + }, + expErr: true, + expStored: &group.GroupInfo{ + GroupId: groupID, + Admin: oldAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx, _ := s.sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + _, err := s.msgClient.UpdateGroupMetadata(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // then + res, err := s.queryClient.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) + s.Require().NoError(err) + s.Assert().Equal(spec.expStored, res.Info) + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupMembers() { + member1 := s.addr5.String() + member2 := s.addr6.String() + members := []group.Member{{ + Address: member1, + Weight: "1", + Metadata: nil, + }} + + myAdmin := s.addr4.String() + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: myAdmin, + Members: members, + Metadata: nil, + }) + s.Require().NoError(err) + groupID := groupRes.GroupId + + specs := map[string]struct { + req *group.MsgUpdateGroupMembers + expErr bool + expGroup *group.GroupInfo + expMembers []*group.GroupMember + }{ + "add new member": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: member2, + Weight: "2", + Metadata: nil, + }}, + }, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "3", + Version: 2, + }, + expMembers: []*group.GroupMember{ + { + Member: &group.Member{ + Address: member2, + Weight: "2", + Metadata: nil, + }, + GroupId: groupID, + }, + { + Member: &group.Member{ + Address: member1, + Weight: "1", + Metadata: nil, + }, + GroupId: groupID, + }, + }, + }, + "update member": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: member1, + Weight: "2", + Metadata: []byte{1, 2, 3}, + }}, + }, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "2", + Version: 2, + }, + expMembers: []*group.GroupMember{ + { + GroupId: groupID, + Member: &group.Member{ + Address: member1, + Weight: "2", + Metadata: []byte{1, 2, 3}, + }, + }, + }, + }, + "update member with same data": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: member1, + Weight: "1", + }}, + }, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 2, + }, + expMembers: []*group.GroupMember{ + { + GroupId: groupID, + Member: &group.Member{ + Address: member1, + Weight: "1", + }, + }, + }, + }, + "replace member": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: myAdmin, + MemberUpdates: []group.Member{ + { + Address: member1, + Weight: "0", + Metadata: nil, + }, + { + Address: member2, + Weight: "1", + Metadata: nil, + }, + }, + }, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 2, + }, + expMembers: []*group.GroupMember{{ + GroupId: groupID, + Member: &group.Member{ + Address: member2, + Weight: "1", + Metadata: nil, + }, + }}, + }, + "remove existing member": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: member1, + Weight: "0", + Metadata: nil, + }}, + }, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "0", + Version: 2, + }, + expMembers: []*group.GroupMember{}, + }, + "remove unknown member": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: s.addr4.String(), + Weight: "0", + Metadata: nil, + }}, + }, + expErr: true, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + expMembers: []*group.GroupMember{{ + GroupId: groupID, + Member: &group.Member{ + Address: member1, + Weight: "1", + Metadata: nil, + }, + }}, + }, + "with wrong admin": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: s.addr3.String(), + MemberUpdates: []group.Member{{ + Address: member1, + Weight: "2", + Metadata: nil, + }}, + }, + expErr: true, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + expMembers: []*group.GroupMember{{ + GroupId: groupID, + Member: &group.Member{ + Address: member1, + Weight: "1", + }, + }}, + }, + "with unknown groupID": { + req: &group.MsgUpdateGroupMembers{ + GroupId: 999, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: member1, + Weight: "2", + Metadata: nil, + }}, + }, + expErr: true, + expGroup: &group.GroupInfo{ + GroupId: groupID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "1", + Version: 1, + }, + expMembers: []*group.GroupMember{{ + GroupId: groupID, + Member: &group.Member{ + Address: member1, + Weight: "1", + }, + }}, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx, _ := s.sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + _, err := s.msgClient.UpdateGroupMembers(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // then + res, err := s.queryClient.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupID}) + s.Require().NoError(err) + s.Assert().Equal(spec.expGroup, res.Info) + + // and members persisted + membersRes, err := s.queryClient.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupID}) + s.Require().NoError(err) + loadedMembers := membersRes.Members + s.Require().Equal(len(spec.expMembers), len(loadedMembers)) + // we reorder group members by address to be able to compare them + sort.Slice(spec.expMembers, func(i, j int) bool { + return spec.expMembers[i].Member.Address < spec.expMembers[j].Member.Address + }) + for i := range loadedMembers { + s.Assert().Equal(spec.expMembers[i].Member.Metadata, loadedMembers[i].Member.Metadata) + s.Assert().Equal(spec.expMembers[i].Member.Address, loadedMembers[i].Member.Address) + s.Assert().Equal(spec.expMembers[i].Member.Weight, loadedMembers[i].Member.Weight) + s.Assert().Equal(spec.expMembers[i].GroupId, loadedMembers[i].GroupId) + } + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupMembersBls() { + member := s.addr3.String() + memberBls1 := s.addrBls1.String() + memberBls2 := s.addrBls2.String() + memberBls3 := s.addrBls3.String() + membersBls := []group.Member{ + { + Address: memberBls1, + Weight: "5", + Metadata: nil, + }, + { + Address: memberBls2, + Weight: "7", + Metadata: nil, + }, + } + + myAdmin := s.addr4.String() + groupBlsRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: myAdmin, + Members: membersBls, + Metadata: nil, + BlsOnly: true, + }) + s.Require().NoError(err) + groupBlsID := groupBlsRes.GroupId + + specs := map[string]struct { + req *group.MsgUpdateGroupMembers + expErr bool + expGroup *group.GroupInfo + expMembers []*group.GroupMember + }{ + "add new bls member": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupBlsID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: memberBls3, + Weight: "3", + Metadata: nil, + }}, + }, + expGroup: &group.GroupInfo{ + GroupId: groupBlsID, + Admin: myAdmin, + Metadata: nil, + TotalWeight: "15", + Version: 2, + BlsOnly: true, + }, + expMembers: []*group.GroupMember{ + { + Member: &group.Member{ + Address: memberBls1, + Weight: "5", + Metadata: nil, + }, + GroupId: groupBlsID, + }, + { + Member: &group.Member{ + Address: memberBls2, + Weight: "7", + Metadata: nil, + }, + GroupId: groupBlsID, + }, + { + Member: &group.Member{ + Address: memberBls3, + Weight: "3", + Metadata: nil, + }, + GroupId: groupBlsID, + }, + }, + }, + "add new non-bls member not allowed": { + req: &group.MsgUpdateGroupMembers{ + GroupId: groupBlsID, + Admin: myAdmin, + MemberUpdates: []group.Member{{ + Address: member, + Weight: "1", + Metadata: nil, + }}, + }, + expErr: true, + }, + } + + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx, _ := s.sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + _, err := s.msgClient.UpdateGroupMembers(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // then + res, err := s.queryClient.GroupInfo(ctx, &group.QueryGroupInfoRequest{GroupId: groupBlsID}) + s.Require().NoError(err) + s.Assert().Equal(spec.expGroup, res.Info) + + // and members persisted + membersRes, err := s.queryClient.GroupMembers(ctx, &group.QueryGroupMembersRequest{GroupId: groupBlsID}) + s.Require().NoError(err) + loadedMembers := membersRes.Members + s.Require().Equal(len(spec.expMembers), len(loadedMembers)) + // we reorder group members by address to be able to compare them + sort.Slice(spec.expMembers, func(i, j int) bool { + return spec.expMembers[i].Member.Address < spec.expMembers[j].Member.Address + }) + for i := range loadedMembers { + s.Assert().Equal(spec.expMembers[i].Member.Metadata, loadedMembers[i].Member.Metadata) + s.Assert().Equal(spec.expMembers[i].Member.Address, loadedMembers[i].Member.Address) + s.Assert().Equal(spec.expMembers[i].Member.Weight, loadedMembers[i].Member.Weight) + s.Assert().Equal(spec.expMembers[i].GroupId, loadedMembers[i].GroupId) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCreateGroupAccount() { + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: nil, + Metadata: nil, + }) + s.Require().NoError(err) + myGroupID := groupRes.GroupId + + specs := map[string]struct { + req *group.MsgCreateGroupAccount + policy group.DecisionPolicy + expErr bool + }{ + "all good": { + req: &group.MsgCreateGroupAccount{ + Admin: s.addr1.String(), + Metadata: nil, + GroupId: myGroupID, + }, + policy: group.NewThresholdDecisionPolicy( + "1", + gogotypes.Duration{Seconds: 1}, + ), + }, + "decision policy threshold > total group weight": { + req: &group.MsgCreateGroupAccount{ + Admin: s.addr1.String(), + Metadata: nil, + GroupId: myGroupID, + }, + policy: group.NewThresholdDecisionPolicy( + "10", + gogotypes.Duration{Seconds: 1}, + ), + }, + "group id does not exists": { + req: &group.MsgCreateGroupAccount{ + Admin: s.addr1.String(), + Metadata: nil, + GroupId: 9999, + }, + policy: group.NewThresholdDecisionPolicy( + "1", + gogotypes.Duration{Seconds: 1}, + ), + expErr: true, + }, + "admin not group admin": { + req: &group.MsgCreateGroupAccount{ + Admin: s.addr4.String(), + Metadata: nil, + GroupId: myGroupID, + }, + policy: group.NewThresholdDecisionPolicy( + "1", + gogotypes.Duration{Seconds: 1}, + ), + expErr: true, + }, + } + + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + err := spec.req.SetDecisionPolicy(spec.policy) + s.Require().NoError(err) + + res, err := s.msgClient.CreateGroupAccount(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + addr := res.Address + + // then all data persisted + groupAccountRes, err := s.queryClient.GroupAccountInfo(s.ctx, &group.QueryGroupAccountInfoRequest{Address: addr}) + s.Require().NoError(err) + + groupAccount := groupAccountRes.Info + s.Assert().Equal(addr, groupAccount.Address) + s.Assert().Equal(myGroupID, groupAccount.GroupId) + s.Assert().Equal(spec.req.Admin, groupAccount.Admin) + s.Assert().Equal(spec.req.Metadata, groupAccount.Metadata) + s.Assert().Equal(uint64(1), groupAccount.Version) + s.Assert().Equal(spec.policy.(*group.ThresholdDecisionPolicy), groupAccount.GetDecisionPolicy()) + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupAccountAdmin() { + admin, newAdmin := s.addr1, s.addr2 + groupAccountAddr, myGroupID, policy, derivationKey := createGroupAndGroupAccount(admin, s) + + specs := map[string]struct { + req *group.MsgUpdateGroupAccountAdmin + expGroupAccount *group.GroupAccountInfo + expErr bool + }{ + "with wrong admin": { + req: &group.MsgUpdateGroupAccountAdmin{ + Admin: s.addr5.String(), + Address: groupAccountAddr, + NewAdmin: newAdmin.String(), + }, + expGroupAccount: &group.GroupAccountInfo{ + Admin: admin.String(), + Address: groupAccountAddr, + GroupId: myGroupID, + Metadata: nil, + Version: 2, + DecisionPolicy: nil, + DerivationKey: derivationKey, + }, + expErr: true, + }, + "with wrong group account": { + req: &group.MsgUpdateGroupAccountAdmin{ + Admin: admin.String(), + Address: s.addr5.String(), + NewAdmin: newAdmin.String(), + }, + expGroupAccount: &group.GroupAccountInfo{ + Admin: admin.String(), + Address: groupAccountAddr, + GroupId: myGroupID, + Metadata: nil, + Version: 2, + DecisionPolicy: nil, + DerivationKey: derivationKey, + }, + expErr: true, + }, + "correct data": { + req: &group.MsgUpdateGroupAccountAdmin{ + Admin: admin.String(), + Address: groupAccountAddr, + NewAdmin: newAdmin.String(), + }, + expGroupAccount: &group.GroupAccountInfo{ + Admin: newAdmin.String(), + Address: groupAccountAddr, + GroupId: myGroupID, + Metadata: nil, + Version: 2, + DecisionPolicy: nil, + DerivationKey: derivationKey, + }, + expErr: false, + }, + } + + for msg, spec := range specs { + spec := spec + err := spec.expGroupAccount.SetDecisionPolicy(policy) + s.Require().NoError(err) + + s.Run(msg, func() { + _, err := s.msgClient.UpdateGroupAccountAdmin(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + res, err := s.queryClient.GroupAccountInfo(s.ctx, &group.QueryGroupAccountInfoRequest{ + Address: groupAccountAddr, + }) + s.Require().NoError(err) + s.Assert().Equal(spec.expGroupAccount, res.Info) + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupAccountMetadata() { + admin := s.addr1 + groupAccountAddr, myGroupID, policy, derivationKey := createGroupAndGroupAccount(admin, s) + + specs := map[string]struct { + req *group.MsgUpdateGroupAccountMetadata + expGroupAccount *group.GroupAccountInfo + expErr bool + }{ + "with wrong admin": { + req: &group.MsgUpdateGroupAccountMetadata{ + Admin: s.addr5.String(), + Address: groupAccountAddr, + Metadata: []byte("hello"), + }, + expGroupAccount: &group.GroupAccountInfo{}, + expErr: true, + }, + "with wrong group account": { + req: &group.MsgUpdateGroupAccountMetadata{ + Admin: admin.String(), + Address: s.addr5.String(), + Metadata: []byte("hello"), + }, + expGroupAccount: &group.GroupAccountInfo{}, + expErr: true, + }, + "with comment too long": { + req: &group.MsgUpdateGroupAccountMetadata{ + Admin: admin.String(), + Address: s.addr5.String(), + Metadata: []byte(strings.Repeat("a", 256)), + }, + expGroupAccount: &group.GroupAccountInfo{}, + expErr: true, + }, + "correct data": { + req: &group.MsgUpdateGroupAccountMetadata{ + Admin: admin.String(), + Address: groupAccountAddr, + Metadata: []byte("hello"), + }, + expGroupAccount: &group.GroupAccountInfo{ + Admin: admin.String(), + Address: groupAccountAddr, + GroupId: myGroupID, + Metadata: []byte("hello"), + Version: 2, + DecisionPolicy: nil, + DerivationKey: derivationKey, + }, + expErr: false, + }, + } + + for msg, spec := range specs { + spec := spec + err := spec.expGroupAccount.SetDecisionPolicy(policy) + s.Require().NoError(err) + + s.Run(msg, func() { + _, err := s.msgClient.UpdateGroupAccountMetadata(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + res, err := s.queryClient.GroupAccountInfo(s.ctx, &group.QueryGroupAccountInfoRequest{ + Address: groupAccountAddr, + }) + s.Require().NoError(err) + s.Assert().Equal(spec.expGroupAccount, res.Info) + }) + } +} + +func (s *IntegrationTestSuite) TestUpdateGroupAccountDecisionPolicy() { + admin := s.addr1 + groupAccountAddr, myGroupID, policy, derivationKey := createGroupAndGroupAccount(admin, s) + + specs := map[string]struct { + req *group.MsgUpdateGroupAccountDecisionPolicy + policy group.DecisionPolicy + expGroupAccount *group.GroupAccountInfo + expErr bool + }{ + "with wrong admin": { + req: &group.MsgUpdateGroupAccountDecisionPolicy{ + Admin: s.addr5.String(), + Address: groupAccountAddr, + }, + policy: policy, + expGroupAccount: &group.GroupAccountInfo{}, + expErr: true, + }, + "with wrong group account": { + req: &group.MsgUpdateGroupAccountDecisionPolicy{ + Admin: admin.String(), + Address: s.addr5.String(), + }, + policy: policy, + expGroupAccount: &group.GroupAccountInfo{}, + expErr: true, + }, + "correct data": { + req: &group.MsgUpdateGroupAccountDecisionPolicy{ + Admin: admin.String(), + Address: groupAccountAddr, + }, + policy: group.NewThresholdDecisionPolicy( + "2", + gogotypes.Duration{Seconds: 2}, + ), + expGroupAccount: &group.GroupAccountInfo{ + Admin: admin.String(), + Address: groupAccountAddr, + GroupId: myGroupID, + Metadata: nil, + Version: 2, + DecisionPolicy: nil, + DerivationKey: derivationKey, + }, + expErr: false, + }, + } + + for msg, spec := range specs { + spec := spec + err := spec.expGroupAccount.SetDecisionPolicy(spec.policy) + s.Require().NoError(err) + + err = spec.req.SetDecisionPolicy(spec.policy) + s.Require().NoError(err) + + s.Run(msg, func() { + _, err := s.msgClient.UpdateGroupAccountDecisionPolicy(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + res, err := s.queryClient.GroupAccountInfo(s.ctx, &group.QueryGroupAccountInfoRequest{ + Address: groupAccountAddr, + }) + s.Require().NoError(err) + s.Assert().Equal(spec.expGroupAccount, res.Info) + }) + } +} + +func (s *IntegrationTestSuite) TestGroupAccountsByAdminOrGroup() { + admin := s.addr2 + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: admin.String(), + Members: nil, + Metadata: nil, + }) + s.Require().NoError(err) + myGroupID := groupRes.GroupId + + policies := []group.DecisionPolicy{ + group.NewThresholdDecisionPolicy( + "1", + gogotypes.Duration{Seconds: 1}, + ), + group.NewThresholdDecisionPolicy( + "10", + gogotypes.Duration{Seconds: 1}, + ), + } + + count := 2 + expectAccs := make([]*group.GroupAccountInfo, count) + for i := range expectAccs { + req := &group.MsgCreateGroupAccount{ + Admin: admin.String(), + Metadata: nil, + GroupId: myGroupID, + } + err := req.SetDecisionPolicy(policies[i]) + s.Require().NoError(err) + res, err := s.msgClient.CreateGroupAccount(s.ctx, req) + s.Require().NoError(err) + + expectAcc := &group.GroupAccountInfo{ + Address: res.Address, + Admin: admin.String(), + Metadata: nil, + GroupId: myGroupID, + Version: uint64(1), + } + err = expectAcc.SetDecisionPolicy(policies[i]) + s.Require().NoError(err) + expectAccs[i] = expectAcc + } + sort.Slice(expectAccs, func(i, j int) bool { return expectAccs[i].Address < expectAccs[j].Address }) + + // query group account by group + accountsByGroupRes, err := s.queryClient.GroupAccountsByGroup(s.ctx, &group.QueryGroupAccountsByGroupRequest{ + GroupId: myGroupID, + }) + s.Require().NoError(err) + accounts := accountsByGroupRes.GroupAccounts + s.Require().Equal(len(accounts), count) + // we reorder accounts by address to be able to compare them + sort.Slice(accounts, func(i, j int) bool { return accounts[i].Address < accounts[j].Address }) + for i := range accounts { + s.Assert().Equal(accounts[i].Address, expectAccs[i].Address) + s.Assert().Equal(accounts[i].GroupId, expectAccs[i].GroupId) + s.Assert().Equal(accounts[i].Admin, expectAccs[i].Admin) + s.Assert().Equal(accounts[i].Metadata, expectAccs[i].Metadata) + s.Assert().Equal(accounts[i].Version, expectAccs[i].Version) + s.Assert().Equal(accounts[i].GetDecisionPolicy(), expectAccs[i].GetDecisionPolicy()) + } + + // query group account by admin + accountsByAdminRes, err := s.queryClient.GroupAccountsByAdmin(s.ctx, &group.QueryGroupAccountsByAdminRequest{ + Admin: admin.String(), + }) + s.Require().NoError(err) + accounts = accountsByAdminRes.GroupAccounts + s.Require().Equal(len(accounts), count) + // we reorder accounts by address to be able to compare them + sort.Slice(accounts, func(i, j int) bool { return accounts[i].Address < accounts[j].Address }) + for i := range accounts { + s.Assert().Equal(accounts[i].Address, expectAccs[i].Address) + s.Assert().Equal(accounts[i].GroupId, expectAccs[i].GroupId) + s.Assert().Equal(accounts[i].Admin, expectAccs[i].Admin) + s.Assert().Equal(accounts[i].Metadata, expectAccs[i].Metadata) + s.Assert().Equal(accounts[i].Version, expectAccs[i].Version) + s.Assert().Equal(accounts[i].GetDecisionPolicy(), expectAccs[i].GetDecisionPolicy()) + } +} + +func (s *IntegrationTestSuite) TestCreateProposal() { + myGroupID := s.groupID + accountAddr := s.groupAccountAddr + + msgSend := &banktypes.MsgSend{ + FromAddress: s.groupAccountAddr.String(), + ToAddress: s.addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + } + + accountReq := &group.MsgCreateGroupAccount{ + Admin: s.addr1.String(), + GroupId: myGroupID, + Metadata: nil, + } + policy := group.NewThresholdDecisionPolicy( + "100", + gogotypes.Duration{Seconds: 1}, + ) + err := accountReq.SetDecisionPolicy(policy) + s.Require().NoError(err) + bigThresholdRes, err := s.msgClient.CreateGroupAccount(s.ctx, accountReq) + s.Require().NoError(err) + bigThresholdAddr := bigThresholdRes.Address + + defaultProposal := group.Proposal{ + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + ExecutorResult: group.ProposalExecutorResultNotRun, + } + + specs := map[string]struct { + req *group.MsgCreateProposal + msgs []sdk.Msg + expProposal group.Proposal + expErr bool + postRun func(sdkCtx sdk.Context) + }{ + "all good with minimal fields set": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr2.String()}, + }, + expProposal: defaultProposal, + postRun: func(sdkCtx sdk.Context) {}, + }, + "all good with good msg payload": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr2.String()}, + }, + msgs: []sdk.Msg{&banktypes.MsgSend{ + FromAddress: accountAddr.String(), + ToAddress: s.addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("token", 100)}, + }}, + expProposal: defaultProposal, + postRun: func(sdkCtx sdk.Context) {}, + }, + "group account required": { + req: &group.MsgCreateProposal{ + Metadata: nil, + Proposers: []string{s.addr2.String()}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "existing group account required": { + req: &group.MsgCreateProposal{ + Address: s.addr1.String(), + Proposers: []string{s.addr2.String()}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "impossible case: decision policy threshold > total group weight": { + req: &group.MsgCreateProposal{ + Address: bigThresholdAddr, + Proposers: []string{s.addr2.String()}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "only group members can create a proposal": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr4.String()}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "all proposers must be in group": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr2.String(), s.addr4.String()}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "proposers must not be empty": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr2.String(), ""}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "admin that is not a group member can not create proposal": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Metadata: nil, + Proposers: []string{s.addr1.String()}, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "reject msgs that are not authz by group account": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Metadata: nil, + Proposers: []string{s.addr2.String()}, + }, + msgs: []sdk.Msg{&testdata.MsgAuthenticated{Signers: []sdk.AccAddress{s.addr1}}}, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "with try exec": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr2.String()}, + Exec: group.Exec_EXEC_TRY, + }, + msgs: []sdk.Msg{msgSend}, + expProposal: group.Proposal{ + Status: group.ProposalStatusClosed, + Result: group.ProposalResultAccepted, + VoteState: group.Tally{ + YesCount: "2", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + ExecutorResult: group.ProposalExecutorResultSuccess, + }, + postRun: func(sdkCtx sdk.Context) { + fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, accountAddr) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 9900)}, fromBalances) + toBalances := s.bankKeeper.GetAllBalances(sdkCtx, s.addr2) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 100)}, toBalances) + }, + }, + "with try exec, not enough yes votes for proposal to pass": { + req: &group.MsgCreateProposal{ + Address: accountAddr.String(), + Proposers: []string{s.addr5.String()}, + Exec: group.Exec_EXEC_TRY, + }, + msgs: []sdk.Msg{msgSend}, + expProposal: group.Proposal{ + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultUnfinalized, + VoteState: group.Tally{ + YesCount: "1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + ExecutorResult: group.ProposalExecutorResultNotRun, + }, + postRun: func(sdkCtx sdk.Context) {}, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + err := spec.req.SetMsgs(spec.msgs) + s.Require().NoError(err) + + res, err := s.msgClient.CreateProposal(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + id := res.ProposalId + + // then all data persisted + proposalRes, err := s.queryClient.Proposal(s.ctx, &group.QueryProposalRequest{ProposalId: id}) + s.Require().NoError(err) + proposal := proposalRes.Proposal + + s.Assert().Equal(accountAddr.String(), proposal.Address) + s.Assert().Equal(spec.req.Metadata, proposal.Metadata) + s.Assert().Equal(spec.req.Proposers, proposal.Proposers) + + submittedAt, err := gogotypes.TimestampFromProto(&proposal.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + s.Assert().Equal(uint64(1), proposal.GroupVersion) + s.Assert().Equal(uint64(1), proposal.GroupAccountVersion) + s.Assert().Equal(spec.expProposal.Status, proposal.Status) + s.Assert().Equal(spec.expProposal.Result, proposal.Result) + s.Assert().Equal(spec.expProposal.VoteState, proposal.VoteState) + s.Assert().Equal(spec.expProposal.ExecutorResult, proposal.ExecutorResult) + + timeout, err := gogotypes.TimestampFromProto(&proposal.Timeout) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime.Add(time.Second), timeout) + + if spec.msgs == nil { // then empty list is ok + s.Assert().Len(proposal.GetMsgs(), 0) + } else { + s.Assert().Equal(spec.msgs, proposal.GetMsgs()) + } + + spec.postRun(s.sdkCtx) + }) + } +} + +func (s *IntegrationTestSuite) TestVote() { + members := []group.Member{ + {Address: s.addr4.String(), Weight: "1"}, + {Address: s.addr3.String(), Weight: "2"}, + } + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: members, + Metadata: nil, + }) + s.Require().NoError(err) + myGroupID := groupRes.GroupId + + policy := group.NewThresholdDecisionPolicy( + "2", + gogotypes.Duration{Seconds: 1}, + ) + accountReq := &group.MsgCreateGroupAccount{ + Admin: s.addr1.String(), + GroupId: myGroupID, + Metadata: nil, + } + err = accountReq.SetDecisionPolicy(policy) + s.Require().NoError(err) + accountRes, err := s.msgClient.CreateGroupAccount(s.ctx, accountReq) + s.Require().NoError(err) + accountAddr := accountRes.Address + groupAccount, err := sdk.AccAddressFromBech32(accountAddr) + s.Require().NoError(err) + s.Require().NotNil(groupAccount) + + s.Require().NoError(fundAccount(s.bankKeeper, s.sdkCtx, groupAccount, sdk.Coins{sdk.NewInt64Coin("test", 10000)})) + + req := &group.MsgCreateProposal{ + Address: accountAddr, + Metadata: nil, + Proposers: []string{s.addr4.String()}, + Msgs: nil, + } + err = req.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ + FromAddress: accountAddr, + ToAddress: s.addr5.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + }}) + s.Require().NoError(err) + + proposalRes, err := s.msgClient.CreateProposal(s.ctx, req) + s.Require().NoError(err) + myProposalID := proposalRes.ProposalId + + // proposals by group account + proposalsRes, err := s.queryClient.ProposalsByGroupAccount(s.ctx, &group.QueryProposalsByGroupAccountRequest{ + Address: accountAddr, + }) + s.Require().NoError(err) + proposals := proposalsRes.Proposals + s.Require().Equal(len(proposals), 1) + s.Assert().Equal(req.Address, proposals[0].Address) + s.Assert().Equal(req.Metadata, proposals[0].Metadata) + s.Assert().Equal(req.Proposers, proposals[0].Proposers) + + submittedAt, err := gogotypes.TimestampFromProto(&proposals[0].SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + s.Assert().Equal(uint64(1), proposals[0].GroupVersion) + s.Assert().Equal(uint64(1), proposals[0].GroupAccountVersion) + s.Assert().Equal(group.ProposalStatusSubmitted, proposals[0].Status) + s.Assert().Equal(group.ProposalResultUnfinalized, proposals[0].Result) + s.Assert().Equal(group.Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, proposals[0].VoteState) + + specs := map[string]struct { + srcCtx sdk.Context + expVoteState group.Tally + req *group.MsgVote + doBefore func(ctx context.Context) + postRun func(sdkCtx sdk.Context) + expProposalStatus group.Proposal_Status + expResult group.Proposal_Result + expExecutorResult group.Proposal_ExecutorResult + expErr bool + }{ + "vote yes": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_YES, + }, + expVoteState: group.Tally{ + YesCount: "1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusSubmitted, + expResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) {}, + }, + "with try exec": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr3.String(), + Choice: group.Choice_CHOICE_YES, + Exec: group.Exec_EXEC_TRY, + }, + expVoteState: group.Tally{ + YesCount: "2", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusClosed, + expResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultSuccess, + postRun: func(sdkCtx sdk.Context) { + fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, groupAccount) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 9900)}, fromBalances) + toBalances := s.bankKeeper.GetAllBalances(sdkCtx, s.addr2) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 100)}, toBalances) + }, + }, + "with try exec, not enough yes votes for proposal to pass": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_YES, + Exec: group.Exec_EXEC_TRY, + }, + expVoteState: group.Tally{ + YesCount: "1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusSubmitted, + expResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) {}, + }, + "vote no": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + expVoteState: group.Tally{ + YesCount: "0", + NoCount: "1", + AbstainCount: "0", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusSubmitted, + expResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) {}, + }, + "vote abstain": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_ABSTAIN, + }, + expVoteState: group.Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "1", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusSubmitted, + expResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) {}, + }, + "vote veto": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_VETO, + }, + expVoteState: group.Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "1", + }, + expProposalStatus: group.ProposalStatusSubmitted, + expResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) {}, + }, + "apply decision policy early": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr3.String(), + Choice: group.Choice_CHOICE_YES, + }, + expVoteState: group.Tally{ + YesCount: "2", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusClosed, + expResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) {}, + }, + "reject new votes when final decision is made already": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_YES, + }, + doBefore: func(ctx context.Context) { + _, err := s.msgClient.Vote(ctx, &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr3.String(), + Choice: group.Choice_CHOICE_VETO, + }) + s.Require().NoError(err) + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "existing proposal required": { + req: &group.MsgVote{ + ProposalId: 999, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "empty choice": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "invalid choice": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: 5, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "voter must be in group": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr2.String(), + Choice: group.Choice_CHOICE_NO, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "voter must not be empty": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: "", + Choice: group.Choice_CHOICE_NO, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "voters must not be nil": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Choice: group.Choice_CHOICE_NO, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "admin that is not a group member can not vote": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr1.String(), + Choice: group.Choice_CHOICE_NO, + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "on timeout": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + srcCtx: s.sdkCtx.WithBlockTime(s.blockTime.Add(time.Second)), + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "closed already": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + doBefore: func(ctx context.Context) { + _, err := s.msgClient.Vote(ctx, &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr3.String(), + Choice: group.Choice_CHOICE_YES, + }) + s.Require().NoError(err) + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "voted already": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + doBefore: func(ctx context.Context) { + _, err := s.msgClient.Vote(ctx, &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_YES, + }) + s.Require().NoError(err) + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "with group modified": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + doBefore: func(ctx context.Context) { + _, err = s.msgClient.UpdateGroupMetadata(ctx, &group.MsgUpdateGroupMetadata{ + GroupId: myGroupID, + Admin: s.addr1.String(), + Metadata: []byte{1, 2, 3}, + }) + s.Require().NoError(err) + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + "with policy modified": { + req: &group.MsgVote{ + ProposalId: myProposalID, + Voter: s.addr4.String(), + Choice: group.Choice_CHOICE_NO, + }, + doBefore: func(ctx context.Context) { + m, err := group.NewMsgUpdateGroupAccountDecisionPolicyRequest( + s.addr1, + groupAccount, + &group.ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: gogotypes.Duration{Seconds: 1}, + }, + ) + s.Require().NoError(err) + + _, err = s.msgClient.UpdateGroupAccountDecisionPolicy(ctx, m) + s.Require().NoError(err) + }, + expErr: true, + postRun: func(sdkCtx sdk.Context) {}, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx := s.sdkCtx + if !spec.srcCtx.IsZero() { + sdkCtx = spec.srcCtx + } + sdkCtx, _ = sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + + if spec.doBefore != nil { + spec.doBefore(ctx) + } + _, err := s.msgClient.Vote(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + s.Require().NoError(err) + // vote is stored and all data persisted + res, err := s.queryClient.VoteByProposalVoter(ctx, &group.QueryVoteByProposalVoterRequest{ + ProposalId: spec.req.ProposalId, + Voter: spec.req.Voter, + }) + s.Require().NoError(err) + loaded := res.Vote + s.Assert().Equal(spec.req.ProposalId, loaded.ProposalId) + s.Assert().Equal(spec.req.Voter, loaded.Voter) + s.Assert().Equal(spec.req.Choice, loaded.Choice) + s.Assert().Equal(spec.req.Metadata, loaded.Metadata) + submittedAt, err := gogotypes.TimestampFromProto(&loaded.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + // query votes by proposal + votesByProposalRes, err := s.queryClient.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ + ProposalId: spec.req.ProposalId, + }) + s.Require().NoError(err) + votesByProposal := votesByProposalRes.Votes + s.Require().Equal(1, len(votesByProposal)) + vote := votesByProposal[0] + s.Assert().Equal(spec.req.ProposalId, vote.ProposalId) + s.Assert().Equal(spec.req.Voter, vote.Voter) + s.Assert().Equal(spec.req.Choice, vote.Choice) + s.Assert().Equal(spec.req.Metadata, vote.Metadata) + submittedAt, err = gogotypes.TimestampFromProto(&vote.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + // query votes by voter + voter := spec.req.Voter + votesByVoterRes, err := s.queryClient.VotesByVoter(ctx, &group.QueryVotesByVoterRequest{ + Voter: voter, + }) + s.Require().NoError(err) + votesByVoter := votesByVoterRes.Votes + s.Require().Equal(1, len(votesByVoter)) + s.Assert().Equal(spec.req.ProposalId, votesByVoter[0].ProposalId) + s.Assert().Equal(voter, votesByVoter[0].Voter) + s.Assert().Equal(spec.req.Choice, votesByVoter[0].Choice) + s.Assert().Equal(spec.req.Metadata, votesByVoter[0].Metadata) + submittedAt, err = gogotypes.TimestampFromProto(&votesByVoter[0].SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + // and proposal is updated + proposalRes, err := s.queryClient.Proposal(ctx, &group.QueryProposalRequest{ + ProposalId: spec.req.ProposalId, + }) + s.Require().NoError(err) + proposal := proposalRes.Proposal + s.Assert().Equal(spec.expVoteState, proposal.VoteState) + s.Assert().Equal(spec.expResult, proposal.Result) + s.Assert().Equal(spec.expProposalStatus, proposal.Status) + s.Assert().Equal(spec.expExecutorResult, proposal.ExecutorResult) + + spec.postRun(sdkCtx) + }) + } +} + +// todo: add test for timeout +func (s *IntegrationTestSuite) TestVoteAgg() { + members := []group.Member{ + {Address: s.addrBls1.String(), Weight: "1"}, + {Address: s.addrBls2.String(), Weight: "2"}, + {Address: s.addrBls3.String(), Weight: "3"}, + {Address: s.addrBls4.String(), Weight: "4"}, + {Address: s.addrBls5.String(), Weight: "5"}, + } + + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: s.addrBls6.String(), + Members: members, + Metadata: nil, + BlsOnly: true, + }) + s.Require().NoError(err) + myGroupID := groupRes.GroupId + + policy := group.NewThresholdDecisionPolicy( + "8", + gogotypes.Duration{Seconds: 20}, + ) + accountReq := &group.MsgCreateGroupAccount{ + Admin: s.addrBls6.String(), + GroupId: myGroupID, + Metadata: nil, + } + err = accountReq.SetDecisionPolicy(policy) + s.Require().NoError(err) + accountRes, err := s.msgClient.CreateGroupAccount(s.ctx, accountReq) + s.Require().NoError(err) + accountAddr := accountRes.Address + groupAccount, err := sdk.AccAddressFromBech32(accountAddr) + s.Require().NoError(err) + s.Require().NotNil(groupAccount) + + s.Require().NoError(fundAccount(s.bankKeeper, s.sdkCtx, groupAccount, sdk.Coins{sdk.NewInt64Coin("test", 10000)})) + + req := &group.MsgCreateProposal{ + Address: accountAddr, + Metadata: nil, + Proposers: []string{s.addrBls1.String()}, + Msgs: nil, + } + err = req.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ + FromAddress: accountAddr, + ToAddress: s.addrBls1.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + }}) + s.Require().NoError(err) + + proposalRes, err := s.msgClient.CreateProposal(s.ctx, req) + s.Require().NoError(err) + myProposalID := proposalRes.ProposalId + + // proposals by group account + proposalsRes, err := s.queryClient.ProposalsByGroupAccount(s.ctx, &group.QueryProposalsByGroupAccountRequest{ + Address: accountAddr, + }) + s.Require().NoError(err) + proposals := proposalsRes.Proposals + s.Require().Equal(len(proposals), 1) + s.Assert().Equal(req.Address, proposals[0].Address) + s.Assert().Equal(req.Metadata, proposals[0].Metadata) + s.Assert().Equal(req.Proposers, proposals[0].Proposers) + + submittedAt, err := gogotypes.TimestampFromProto(&proposals[0].SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + s.Assert().Equal(uint64(1), proposals[0].GroupVersion) + s.Assert().Equal(uint64(1), proposals[0].GroupAccountVersion) + s.Assert().Equal(group.ProposalStatusSubmitted, proposals[0].Status) + s.Assert().Equal(group.ProposalResultUnfinalized, proposals[0].Result) + s.Assert().Equal(group.Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, proposals[0].VoteState) + + voteAggTimeout, err := gogotypes.TimestampProto(submittedAt.Add(time.Second * 10)) + s.Require().NoError(err) + + type fullVote struct { + Address string + Choice group.Choice + } + + rawVotesAcc := []fullVote{ + {Address: s.addrBls1.String(), Choice: group.Choice_CHOICE_YES}, + {Address: s.addrBls2.String(), Choice: group.Choice_CHOICE_NO}, + {Address: s.addrBls3.String(), Choice: group.Choice_CHOICE_YES}, + {Address: s.addrBls4.String(), Choice: group.Choice_CHOICE_UNSPECIFIED}, + {Address: s.addrBls5.String(), Choice: group.Choice_CHOICE_YES}, + } + sort.Slice(rawVotesAcc, func(i, j int) bool { return rawVotesAcc[i].Address < rawVotesAcc[j].Address }) + sortedVotesAcc := make([]group.Choice, len(rawVotesAcc)) + validVotesAcc := make([]fullVote, 0, len(rawVotesAcc)) + for i, v := range rawVotesAcc { + sortedVotesAcc[i] = v.Choice + if v.Choice != group.Choice_CHOICE_UNSPECIFIED { + validVotesAcc = append(validVotesAcc, v) + } + } + + rawVotesRej := []fullVote{ + {Address: s.addrBls1.String(), Choice: group.Choice_CHOICE_YES}, + {Address: s.addrBls2.String(), Choice: group.Choice_CHOICE_ABSTAIN}, + {Address: s.addrBls3.String(), Choice: group.Choice_CHOICE_NO}, + {Address: s.addrBls4.String(), Choice: group.Choice_CHOICE_UNSPECIFIED}, + {Address: s.addrBls5.String(), Choice: group.Choice_CHOICE_VETO}, + } + sort.Slice(rawVotesRej, func(i, j int) bool { return rawVotesRej[i].Address < rawVotesRej[j].Address }) + sortedVotesRej := make([]group.Choice, len(rawVotesRej)) + validVotesRej := make([]fullVote, 0, len(rawVotesRej)) + for i, v := range rawVotesRej { + sortedVotesRej[i] = v.Choice + if v.Choice != group.Choice_CHOICE_UNSPECIFIED { + validVotesRej = append(validVotesRej, v) + } + } + + msgNo := &group.MsgVoteBasic{ + ProposalId: myProposalID, + Choice: group.Choice_CHOICE_NO, + Expiry: *voteAggTimeout, + } + signBytesNo := msgNo.GetSignBytes() + + msgYes := &group.MsgVoteBasic{ + ProposalId: myProposalID, + Choice: group.Choice_CHOICE_YES, + Expiry: *voteAggTimeout, + } + signBytesYes := msgYes.GetSignBytes() + + msgAbstain := &group.MsgVoteBasic{ + ProposalId: myProposalID, + Choice: group.Choice_CHOICE_ABSTAIN, + Expiry: *voteAggTimeout, + } + signBytesAbstain := msgAbstain.GetSignBytes() + + msgVeto := &group.MsgVoteBasic{ + ProposalId: myProposalID, + Choice: group.Choice_CHOICE_VETO, + Expiry: *voteAggTimeout, + } + signBytesVeto := msgVeto.GetSignBytes() + + sig1, err := s.skBls1.Sign(signBytesYes) + s.Require().NoError(err) + sig2, err := s.skBls2.Sign(signBytesNo) + s.Require().NoError(err) + sig3, err := s.skBls3.Sign(signBytesYes) + s.Require().NoError(err) + sig5, err := s.skBls5.Sign(signBytesYes) + s.Require().NoError(err) + sigmaAcc, err := bls12381.AggregateSignature([][]byte{sig1, sig2, sig3, sig5}) + s.Require().NoError(err) + + sig1, err = s.skBls1.Sign(signBytesYes) + s.Require().NoError(err) + sig2, err = s.skBls2.Sign(signBytesAbstain) + s.Require().NoError(err) + sig3, err = s.skBls3.Sign(signBytesNo) + s.Require().NoError(err) + sig5, err = s.skBls5.Sign(signBytesVeto) + s.Require().NoError(err) + sigmaRej, err := bls12381.AggregateSignature([][]byte{sig1, sig2, sig3, sig5}) + s.Require().NoError(err) + + specs := map[string]struct { + srcCtx sdk.Context + expVoteState group.Tally + req *group.MsgVoteAgg + votes []fullVote + doBefore func(ctx context.Context) + postRun func(sdkCtx sdk.Context) + expProposalStatus group.Proposal_Status + expResult group.Proposal_Result + expExecutorResult group.Proposal_ExecutorResult + expErr bool + }{ + "result accepted with exec": { + req: &group.MsgVoteAgg{ + Sender: s.addr1.String(), + ProposalId: myProposalID, + Votes: sortedVotesAcc, + Expiry: *voteAggTimeout, + AggSig: sigmaAcc, + Exec: group.Exec_EXEC_TRY, + }, + votes: validVotesAcc, + expVoteState: group.Tally{ + YesCount: "9", + NoCount: "2", + AbstainCount: "0", + VetoCount: "0", + }, + expProposalStatus: group.ProposalStatusClosed, + expResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultSuccess, + postRun: func(sdkCtx sdk.Context) { + fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, groupAccount) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 9900)}, fromBalances) + toBalances := s.bankKeeper.GetAllBalances(sdkCtx, s.addrBls1) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 100)}, toBalances) + }, + }, + "result rejected": { + req: &group.MsgVoteAgg{ + Sender: s.addr1.String(), + ProposalId: myProposalID, + Votes: sortedVotesRej, + Expiry: *voteAggTimeout, + AggSig: sigmaRej, + Exec: group.Exec_EXEC_TRY, + }, + votes: validVotesRej, + expVoteState: group.Tally{ + YesCount: "1", + NoCount: "3", + AbstainCount: "2", + VetoCount: "5", + }, + expProposalStatus: group.ProposalStatusClosed, + expResult: group.ProposalResultRejected, + expExecutorResult: group.ProposalExecutorResultNotRun, + postRun: func(sdkCtx sdk.Context) { + fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, groupAccount) + s.Require().Equal(sdk.Coins{sdk.NewInt64Coin("test", 10000)}, fromBalances) + toBalances := s.bankKeeper.GetAllBalances(sdkCtx, s.addrBls1) + s.Require().Equal(sdk.Coins{}, toBalances) + }, + }, + "invalid signature": { + req: &group.MsgVoteAgg{ + Sender: s.addr1.String(), + ProposalId: myProposalID, + Votes: sortedVotesAcc, + Expiry: *voteAggTimeout, + AggSig: sigmaRej, + Exec: group.Exec_EXEC_TRY, + }, + expErr: true, + }, + } + + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx := s.sdkCtx + if !spec.srcCtx.IsZero() { + sdkCtx = spec.srcCtx + } + sdkCtx, _ = sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + + if spec.doBefore != nil { + spec.doBefore(ctx) + } + _, err := s.msgClient.VoteAgg(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // query votes by proposal + votesByProposalRes, err := s.queryClient.VotesByProposal(ctx, &group.QueryVotesByProposalRequest{ + ProposalId: spec.req.ProposalId, + }) + s.Require().NoError(err) + votesByProposal := votesByProposalRes.Votes + s.Require().Equal(len(spec.votes), len(votesByProposal)) + + for i, vote := range votesByProposal { + s.Assert().Equal(spec.req.ProposalId, vote.ProposalId) + s.Assert().Equal(spec.votes[i].Address, vote.Voter) + s.Assert().Equal(spec.votes[i].Choice, vote.Choice) + submittedAt, err = gogotypes.TimestampFromProto(&vote.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + } + + // query votes by voter + for _, vote := range spec.votes { + votesByVoterRes, err := s.queryClient.VotesByVoter(ctx, &group.QueryVotesByVoterRequest{ + Voter: vote.Address, + }) + s.Require().NoError(err) + votesByVoter := votesByVoterRes.Votes + s.Require().Equal(1, len(votesByVoter)) + s.Assert().Equal(spec.req.ProposalId, votesByVoter[0].ProposalId) + s.Assert().Equal(vote.Address, votesByVoter[0].Voter) + s.Assert().Equal(vote.Choice, votesByVoter[0].Choice) + submittedAt, err = gogotypes.TimestampFromProto(&votesByVoter[0].SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + } + + // and proposal is updated + proposalRes, err := s.queryClient.Proposal(ctx, &group.QueryProposalRequest{ + ProposalId: spec.req.ProposalId, + }) + s.Require().NoError(err) + proposal := proposalRes.Proposal + s.Assert().Equal(spec.expVoteState, proposal.VoteState) + s.Assert().Equal(spec.expResult, proposal.Result) + s.Assert().Equal(spec.expProposalStatus, proposal.Status) + s.Assert().Equal(spec.expExecutorResult, proposal.ExecutorResult) + + spec.postRun(sdkCtx) + }) + } + +} + +func (s *IntegrationTestSuite) TestExecProposal() { + msgSend1 := &banktypes.MsgSend{ + FromAddress: s.groupAccountAddr.String(), + ToAddress: s.addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + } + msgSend2 := &banktypes.MsgSend{ + FromAddress: s.groupAccountAddr.String(), + ToAddress: s.addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 10001)}, + } + proposers := []string{s.addr2.String()} + + specs := map[string]struct { + srcBlockTime time.Time + setupProposal func(ctx context.Context) uint64 + expErr bool + expProposalStatus group.Proposal_Status + expProposalResult group.Proposal_Result + expExecutorResult group.Proposal_ExecutorResult + expFromBalances sdk.Coins + expToBalances sdk.Coins + }{ + "proposal executed when accepted": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend1} + return createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_YES) + }, + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultSuccess, + expFromBalances: sdk.Coins{sdk.NewInt64Coin("test", 9800)}, + expToBalances: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + }, + "proposal with multiple messages executed when accepted": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend1, msgSend1} + return createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_YES) + }, + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultSuccess, + expFromBalances: sdk.Coins{sdk.NewInt64Coin("test", 9700)}, + expToBalances: sdk.Coins{sdk.NewInt64Coin("test", 300)}, + }, + "proposal not executed when rejected": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend1} + return createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_NO) + }, + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultRejected, + expExecutorResult: group.ProposalExecutorResultNotRun, + }, + "open proposal must not fail": { + setupProposal: func(ctx context.Context) uint64 { + return createProposal(ctx, s, []sdk.Msg{msgSend1}, proposers) + }, + expProposalStatus: group.ProposalStatusSubmitted, + expProposalResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + }, + "existing proposal required": { + setupProposal: func(ctx context.Context) uint64 { + return 9999 + }, + expErr: true, + }, + "Decision policy also applied on timeout": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend1} + return createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_NO) + }, + srcBlockTime: s.blockTime.Add(time.Second), + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultRejected, + expExecutorResult: group.ProposalExecutorResultNotRun, + }, + "Decision policy also applied after timeout": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend1} + return createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_NO) + }, + srcBlockTime: s.blockTime.Add(time.Second).Add(time.Millisecond), + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultRejected, + expExecutorResult: group.ProposalExecutorResultNotRun, + }, + "with group modified before tally": { + setupProposal: func(ctx context.Context) uint64 { + myProposalID := createProposal(ctx, s, []sdk.Msg{msgSend1}, proposers) + + // then modify group + _, err := s.msgClient.UpdateGroupMetadata(ctx, &group.MsgUpdateGroupMetadata{ + Admin: s.addr1.String(), + GroupId: s.groupID, + Metadata: []byte{1, 2, 3}, + }) + s.Require().NoError(err) + return myProposalID + }, + expProposalStatus: group.ProposalStatusAborted, + expProposalResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + }, + "with group account modified before tally": { + setupProposal: func(ctx context.Context) uint64 { + myProposalID := createProposal(ctx, s, []sdk.Msg{msgSend1}, proposers) + _, err := s.msgClient.UpdateGroupAccountMetadata(ctx, &group.MsgUpdateGroupAccountMetadata{ + Admin: s.addr1.String(), + Address: s.groupAccountAddr.String(), + Metadata: []byte("group account modified before tally"), + }) + s.Require().NoError(err) + return myProposalID + }, + expProposalStatus: group.ProposalStatusAborted, + expProposalResult: group.ProposalResultUnfinalized, + expExecutorResult: group.ProposalExecutorResultNotRun, + }, + "prevent double execution when successful": { + setupProposal: func(ctx context.Context) uint64 { + myProposalID := createProposalAndVote(ctx, s, []sdk.Msg{msgSend1}, proposers, group.Choice_CHOICE_YES) + + _, err := s.msgClient.Exec(ctx, &group.MsgExec{Signer: s.addr1.String(), ProposalId: myProposalID}) + s.Require().NoError(err) + return myProposalID + }, + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultSuccess, + expFromBalances: sdk.Coins{sdk.NewInt64Coin("test", 9800)}, + expToBalances: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + }, + "rollback all msg updates on failure": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend1, msgSend2} + return createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_YES) + }, + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultFailure, + }, + "executable when failed before": { + setupProposal: func(ctx context.Context) uint64 { + msgs := []sdk.Msg{msgSend2} + myProposalID := createProposalAndVote(ctx, s, msgs, proposers, group.Choice_CHOICE_YES) + + _, err := s.msgClient.Exec(ctx, &group.MsgExec{Signer: s.addr1.String(), ProposalId: myProposalID}) + s.Require().NoError(err) + s.Require().NoError(fundAccount(s.bankKeeper, ctx.(types.Context).Context, s.groupAccountAddr, sdk.Coins{sdk.NewInt64Coin("test", 10002)})) + + return myProposalID + }, + expProposalStatus: group.ProposalStatusClosed, + expProposalResult: group.ProposalResultAccepted, + expExecutorResult: group.ProposalExecutorResultSuccess, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx, _ := s.sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + + proposalID := spec.setupProposal(ctx) + + if !spec.srcBlockTime.IsZero() { + sdkCtx = sdkCtx.WithBlockTime(spec.srcBlockTime) + ctx = types.Context{Context: sdkCtx} + } + + _, err := s.msgClient.Exec(ctx, &group.MsgExec{Signer: s.addr1.String(), ProposalId: proposalID}) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // and proposal is updated + res, err := s.queryClient.Proposal(ctx, &group.QueryProposalRequest{ProposalId: proposalID}) + s.Require().NoError(err) + proposal := res.Proposal + + exp := group.Proposal_Result_name[int32(spec.expProposalResult)] + got := group.Proposal_Result_name[int32(proposal.Result)] + s.Assert().Equal(exp, got) + + exp = group.Proposal_Status_name[int32(spec.expProposalStatus)] + got = group.Proposal_Status_name[int32(proposal.Status)] + s.Assert().Equal(exp, got) + + exp = group.Proposal_ExecutorResult_name[int32(spec.expExecutorResult)] + got = group.Proposal_ExecutorResult_name[int32(proposal.ExecutorResult)] + s.Assert().Equal(exp, got) + + if spec.expFromBalances != nil { + fromBalances := s.bankKeeper.GetAllBalances(sdkCtx, s.groupAccountAddr) + s.Require().Equal(spec.expFromBalances, fromBalances) + } + if spec.expToBalances != nil { + toBalances := s.bankKeeper.GetAllBalances(sdkCtx, s.addr2) + s.Require().Equal(spec.expToBalances, toBalances) + } + }) + } +} + +func (s *IntegrationTestSuite) TestCreatePoll() { + myGroupID := s.groupID + now := s.blockTime + endTime, err := gogotypes.TimestampProto(now.Add(time.Second * 100)) + s.Require().NoError(err) + past := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) + oldTime, err := gogotypes.TimestampProto(past) + + defaultPoll := group.Poll{ + Status: group.PollStatusSubmitted, + } + + specs := map[string]struct { + req *group.MsgCreatePoll + expPoll group.Poll + expErr bool + }{ + "all good": { + req: &group.MsgCreatePoll{ + GroupId: myGroupID, + Title: "2021 Election", + Options: group.Options{Titles: []string{"alice", "bob", "charlie"}}, + Creator: s.addr2.String(), + VoteLimit: 2, + Timeout: *endTime, + }, + expPoll: defaultPoll, + }, + "only group members can create a poll": { + req: &group.MsgCreatePoll{ + GroupId: myGroupID, + Title: "2021 Election", + Options: group.Options{Titles: []string{"alice", "bob", "charlie"}}, + Creator: s.addr4.String(), + VoteLimit: 2, + Timeout: *endTime, + }, + expErr: true, + }, + "admin that is not a group member can not create poll": { + req: &group.MsgCreatePoll{ + GroupId: myGroupID, + Title: "2021 Election", + Options: group.Options{Titles: []string{"alice", "bob", "charlie"}}, + Creator: s.addr1.String(), + VoteLimit: 2, + Timeout: *endTime, + }, + expErr: true, + }, + "poll expired": { + req: &group.MsgCreatePoll{ + GroupId: myGroupID, + Title: "2021 Election", + Options: group.Options{Titles: []string{"alice", "bob", "charlie"}}, + Creator: s.addr2.String(), + VoteLimit: 2, + Timeout: *oldTime, + }, + expErr: true, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + res, err := s.msgClient.CreatePoll(s.ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + id := res.PollId + + // then all data persisted + pollRes, err := s.queryClient.Poll(s.ctx, &group.QueryPollRequest{PollId: id}) + s.Require().NoError(err) + poll := pollRes.Poll + + s.Assert().Equal(spec.req.GroupId, poll.GroupId) + s.Assert().Equal(spec.req.Title, poll.Title) + s.Assert().Equal(spec.req.Options, poll.Options) + s.Assert().Equal(spec.req.Creator, poll.Creator) + s.Assert().Equal(spec.req.VoteLimit, poll.VoteLimit) + s.Assert().Equal(spec.req.Metadata, poll.Metadata) + s.Assert().Equal(spec.req.Timeout, poll.Timeout) + + submittedAt, err := gogotypes.TimestampFromProto(&poll.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + s.Assert().Equal(uint64(1), poll.GroupVersion) + s.Assert().Equal(spec.expPoll.Status, poll.Status) + }) + } +} + +func (s *IntegrationTestSuite) TestVotePoll() { + members := []group.Member{ + {Address: s.addr4.String(), Weight: "1"}, + {Address: s.addr3.String(), Weight: "2"}, + } + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: s.addr1.String(), + Members: members, + Metadata: nil, + }) + s.Require().NoError(err) + myGroupID := groupRes.GroupId + + now := s.blockTime + endTime, err := gogotypes.TimestampProto(now.Add(time.Second * 100)) + req := &group.MsgCreatePoll{ + GroupId: myGroupID, + Title: "2021 Election", + Options: group.Options{Titles: []string{"alice", "bob", "charlie", "linda", "tom"}}, + Creator: s.addr3.String(), + VoteLimit: 2, + Timeout: *endTime, + } + + pollRes, err := s.msgClient.CreatePoll(s.ctx, req) + s.Require().NoError(err) + myPollID := pollRes.PollId + + _, err = s.queryClient.Poll(s.ctx, &group.QueryPollRequest{PollId: myPollID}) + s.Require().NoError(err) + + specs := map[string]struct { + srcCtx sdk.Context + expVoteState group.TallyPoll + req *group.MsgVotePoll + doBefore func(ctx context.Context) + expPollStatus group.Poll_Status + expErr bool + }{ + "all good": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"alice", "bob"}}, + }, + expVoteState: group.TallyPoll{ + Counts: map[string]string{ + "alice": "1", + "bob": "1", + }, + }, + expPollStatus: group.PollStatusSubmitted, + }, + "invalid option": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"eva"}}, + }, + expErr: true, + }, + "on vote limit": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"alice", "bob", "charlie"}}, + }, + expErr: true, + }, + "voter must be in group": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr2.String(), + Options: group.Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "voter must not be empty": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: "", + Options: group.Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "voters must not be nil": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Options: group.Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "admin that is not a group member can not vote": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr1.String(), + Options: group.Options{Titles: []string{"alice"}}, + }, + expErr: true, + }, + "on timeout": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"alice"}}, + }, + srcCtx: s.sdkCtx.WithBlockTime(s.blockTime.Add(time.Second * 101)), + expErr: true, + }, + "multiple votes": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr3.String(), + Options: group.Options{Titles: []string{"alice", "bob"}}, + }, + doBefore: func(ctx context.Context) { + _, err := s.msgClient.VotePoll(ctx, &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"bob"}}, + }) + s.Require().NoError(err) + }, + expVoteState: group.TallyPoll{ + Counts: map[string]string{ + "alice": "2", + "bob": "3", + }, + }, + expPollStatus: group.PollStatusSubmitted, + }, + "voted already": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"alice"}}, + }, + doBefore: func(ctx context.Context) { + _, err := s.msgClient.VotePoll(ctx, &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"bob"}}, + }) + s.Require().NoError(err) + }, + expErr: true, + }, + "with group modified": { + req: &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addr4.String(), + Options: group.Options{Titles: []string{"alice"}}, + }, + doBefore: func(ctx context.Context) { + _, err = s.msgClient.UpdateGroupMetadata(ctx, &group.MsgUpdateGroupMetadata{ + GroupId: myGroupID, + Admin: s.addr1.String(), + Metadata: []byte{1, 2, 3}, + }) + s.Require().NoError(err) + }, + expErr: true, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx := s.sdkCtx + if !spec.srcCtx.IsZero() { + sdkCtx = spec.srcCtx + } + sdkCtx, _ = sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + + if spec.doBefore != nil { + spec.doBefore(ctx) + } + _, err := s.msgClient.VotePoll(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // vote is stored and all data persisted + res, err := s.queryClient.VoteForPollByPollVoter(ctx, &group.QueryVoteForPollByPollVoterRequest{ + PollId: spec.req.PollId, + Voter: spec.req.Voter, + }) + s.Require().NoError(err) + loaded := res.Vote + s.Assert().Equal(spec.req.PollId, loaded.PollId) + s.Assert().Equal(spec.req.Voter, loaded.Voter) + s.Assert().Equal(spec.req.Options, loaded.Options) + s.Assert().Equal(spec.req.Metadata, loaded.Metadata) + submittedAt, err := gogotypes.TimestampFromProto(&loaded.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + // query votes by proposal + votesForPollByPollRes, err := s.queryClient.VotesForPollByPoll(ctx, &group.QueryVotesForPollByPollRequest{ + PollId: spec.req.PollId, + }) + s.Require().NoError(err) + votesByPoll := votesForPollByPollRes.Votes + //s.Require().Equal(1, len(votesByPoll)) + foundVoter := false + for _, vote := range votesByPoll { + if vote.Voter == spec.req.Voter { + foundVoter = true + s.Assert().Equal(spec.req.PollId, vote.PollId) + s.Assert().Equal(spec.req.Voter, vote.Voter) + s.Assert().Equal(spec.req.Options, vote.Options) + s.Assert().Equal(spec.req.Metadata, vote.Metadata) + submittedAt, err = gogotypes.TimestampFromProto(&vote.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + } + } + s.Require().True(foundVoter) + + // query votes by voter + voter := spec.req.Voter + votesByVoterRes, err := s.queryClient.VotesForPollByVoter(ctx, &group.QueryVotesForPollByVoterRequest{ + Voter: voter, + }) + s.Require().NoError(err) + votesByVoter := votesByVoterRes.Votes + s.Require().Equal(1, len(votesByVoter)) + s.Assert().Equal(spec.req.PollId, votesByVoter[0].PollId) + s.Assert().Equal(voter, votesByVoter[0].Voter) + s.Assert().Equal(spec.req.Options, votesByVoter[0].Options) + s.Assert().Equal(spec.req.Metadata, votesByVoter[0].Metadata) + submittedAt, err = gogotypes.TimestampFromProto(&votesByVoter[0].SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + // and poll is updated + pollRes, err := s.queryClient.Poll(ctx, &group.QueryPollRequest{ + PollId: spec.req.PollId, + }) + s.Require().NoError(err) + poll := pollRes.Poll + s.Assert().Equal(spec.expVoteState, poll.VoteState) + }) + } +} + +func (s *IntegrationTestSuite) TestVotePollAgg() { + members := []group.Member{ + {Address: s.addrBls1.String(), Weight: "1"}, + {Address: s.addrBls2.String(), Weight: "2"}, + {Address: s.addrBls3.String(), Weight: "3"}, + {Address: s.addrBls4.String(), Weight: "4"}, + {Address: s.addrBls5.String(), Weight: "5"}, + } + + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: s.addrBls6.String(), + Members: members, + Metadata: nil, + BlsOnly: true, + }) + s.Require().NoError(err) + myGroupID := groupRes.GroupId + + now := s.blockTime + endTime, err := gogotypes.TimestampProto(now.Add(time.Second * 20)) + req := &group.MsgCreatePoll{ + GroupId: myGroupID, + Title: "2021 Election", + Options: group.Options{Titles: []string{"alice", "bob", "charlie", "linda", "tom"}}, + Creator: s.addrBls5.String(), + VoteLimit: 2, + Timeout: *endTime, + } + + pollRes, err := s.msgClient.CreatePoll(s.ctx, req) + s.Require().NoError(err) + myPollID := pollRes.PollId + + pollQuery, err := s.queryClient.Poll(s.ctx, &group.QueryPollRequest{PollId: myPollID}) + s.Require().NoError(err) + submittedAt, err := gogotypes.TimestampFromProto(&pollQuery.Poll.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + + s.Assert().Equal(uint64(1), pollQuery.Poll.GroupVersion) + s.Assert().Equal(group.PollStatusSubmitted, pollQuery.Poll.Status) + + type fullVote struct { + Address string + Options group.Options + } + + // valid votes + rawVotes := []fullVote{ + {Address: s.addrBls1.String(), Options: group.Options{Titles: []string{"alice", "bob"}}}, + {Address: s.addrBls2.String()}, + {Address: s.addrBls3.String(), Options: group.Options{Titles: []string{"alice"}}}, + {Address: s.addrBls4.String()}, + {Address: s.addrBls5.String()}, + } + sort.Slice(rawVotes, func(i, j int) bool { return rawVotes[i].Address < rawVotes[j].Address }) + sortedVotes := make([]group.Options, len(rawVotes)) + validVotes := make([]fullVote, 0, len(rawVotes)) + for i, v := range rawVotes { + sortedVotes[i] = v.Options + if len(v.Options.Titles) != 0 { + validVotes = append(validVotes, v) + } + } + + voteExpiry, err := gogotypes.TimestampProto(submittedAt.Add(time.Second * 10)) + s.Require().NoError(err) + + msgs := make(map[string][]byte, len(req.Options.Titles)) + for _, opt := range req.Options.Titles { + x := group.MsgVotePollBasic{ + PollId: myPollID, + Option: opt, + Expiry: *voteExpiry, + } + msgs[opt] = x.GetSignBytes() + } + + sig11, err := s.skBls1.Sign(msgs["alice"]) + s.Require().NoError(err) + sig12, err := s.skBls1.Sign(msgs["bob"]) + s.Require().NoError(err) + sig1, err := bls12381.AggregateSignature([][]byte{sig11, sig12}) + s.Require().NoError(err) + + sig3, err := s.skBls3.Sign(msgs["alice"]) + s.Require().NoError(err) + + sigma, err := bls12381.AggregateSignature([][]byte{sig1, sig3}) + s.Require().NoError(err) + + // vote too late + rawVotesLate := []fullVote{ + {Address: s.addrBls1.String(), Options: group.Options{Titles: []string{"alice", "bob"}}}, + {Address: s.addrBls2.String()}, + {Address: s.addrBls3.String(), Options: group.Options{Titles: []string{"alice"}}}, + {Address: s.addrBls4.String()}, + {Address: s.addrBls5.String()}, + } + sort.Slice(rawVotesLate, func(i, j int) bool { return rawVotesLate[i].Address < rawVotesLate[j].Address }) + sortedVotesLate := make([]group.Options, len(rawVotesLate)) + for i, v := range rawVotesLate { + sortedVotesLate[i] = v.Options + } + + voteExpiryLate, err := gogotypes.TimestampProto(submittedAt.Add(time.Second * 30)) + s.Require().NoError(err) + + msgsLate := make(map[string][]byte, len(req.Options.Titles)) + for _, opt := range req.Options.Titles { + x := group.MsgVotePollBasic{ + PollId: myPollID, + Option: opt, + Expiry: *voteExpiryLate, + } + msgsLate[opt] = x.GetSignBytes() + } + + sigLate11, err := s.skBls1.Sign(msgsLate["alice"]) + s.Require().NoError(err) + sigLate12, err := s.skBls1.Sign(msgsLate["bob"]) + s.Require().NoError(err) + sigLate1, err := bls12381.AggregateSignature([][]byte{sigLate11, sigLate12}) + s.Require().NoError(err) + + sigLate3, err := s.skBls3.Sign(msgsLate["alice"]) + s.Require().NoError(err) + + sigmaLate, err := bls12381.AggregateSignature([][]byte{sigLate1, sigLate3}) + s.Require().NoError(err) + + // vote limit + rawVotesLong := []fullVote{ + {Address: s.addrBls1.String(), Options: group.Options{Titles: []string{"alice", "bob", "linda"}}}, + {Address: s.addrBls2.String()}, + {Address: s.addrBls3.String(), Options: group.Options{Titles: []string{"alice"}}}, + {Address: s.addrBls4.String()}, + {Address: s.addrBls5.String()}, + } + sort.Slice(rawVotesLong, func(i, j int) bool { return rawVotesLong[i].Address < rawVotesLong[j].Address }) + sortedVotesLong := make([]group.Options, len(rawVotesLong)) + for i, v := range rawVotesLong { + sortedVotesLong[i] = v.Options + } + + msgsLong := make(map[string][]byte, len(req.Options.Titles)) + for _, opt := range req.Options.Titles { + x := group.MsgVotePollBasic{ + PollId: myPollID, + Option: opt, + Expiry: *voteExpiry, + } + msgsLong[opt] = x.GetSignBytes() + } + + sigLong11, err := s.skBls1.Sign(msgsLong["alice"]) + s.Require().NoError(err) + sigLong12, err := s.skBls1.Sign(msgsLong["bob"]) + s.Require().NoError(err) + sigLong13, err := s.skBls1.Sign(msgsLong["linda"]) + s.Require().NoError(err) + sigLong1, err := bls12381.AggregateSignature([][]byte{sigLong11, sigLong12, sigLong13}) + s.Require().NoError(err) + + sigLong3, err := s.skBls3.Sign(msgsLong["alice"]) + s.Require().NoError(err) + + sigmaLong, err := bls12381.AggregateSignature([][]byte{sigLong1, sigLong3}) + s.Require().NoError(err) + + // vote invalid option + rawVotesInvalid := []fullVote{ + {Address: s.addrBls1.String(), Options: group.Options{Titles: []string{"alice", "eva"}}}, + {Address: s.addrBls2.String()}, + {Address: s.addrBls3.String(), Options: group.Options{Titles: []string{"alice"}}}, + {Address: s.addrBls4.String()}, + {Address: s.addrBls5.String()}, + } + sort.Slice(rawVotesInvalid, func(i, j int) bool { return rawVotesInvalid[i].Address < rawVotesInvalid[j].Address }) + sortedVotesInvalid := make([]group.Options, len(rawVotesInvalid)) + for i, v := range rawVotesInvalid { + sortedVotesInvalid[i] = v.Options + } + + msgsInvalid := make(map[string][]byte, len(req.Options.Titles)) + for _, opt := range req.Options.Titles { + x := group.MsgVotePollBasic{ + PollId: myPollID, + Option: opt, + Expiry: *voteExpiry, + } + msgsInvalid[opt] = x.GetSignBytes() + } + + y := group.MsgVotePollBasic{ + PollId: myPollID, + Option: "eva", + Expiry: *voteExpiry, + } + msgsInvalid["eva"] = y.GetSignBytes() + + sigInvalid11, err := s.skBls1.Sign(msgsInvalid["alice"]) + s.Require().NoError(err) + sigInvalid12, err := s.skBls1.Sign(msgsInvalid["eva"]) + s.Require().NoError(err) + sigInvalid1, err := bls12381.AggregateSignature([][]byte{sigInvalid11, sigInvalid12}) + s.Require().NoError(err) + + sigInvalid3, err := s.skBls3.Sign(msgsInvalid["alice"]) + s.Require().NoError(err) + + sigmaInvalid, err := bls12381.AggregateSignature([][]byte{sigInvalid1, sigInvalid3}) + s.Require().NoError(err) + + // skip already voted + validVotesSkip := []fullVote{ + {Address: s.addrBls1.String(), Options: group.Options{Titles: []string{"charlie"}}}, + {Address: s.addrBls3.String(), Options: group.Options{Titles: []string{"alice"}}}, + } + sort.Slice(validVotesSkip, func(i, j int) bool { return validVotesSkip[i].Address < validVotesSkip[j].Address }) + + specs := map[string]struct { + srcCtx sdk.Context + expVoteState group.TallyPoll + req *group.MsgVotePollAgg + votes []fullVote + doBefore func(ctx context.Context) + expPollStatus group.Poll_Status + expErr bool + }{ + "all good": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotes, + Expiry: *voteExpiry, + AggSig: sigma, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + votes: validVotes, + expVoteState: group.TallyPoll{ + Counts: map[string]string{ + "alice": "4", + "bob": "1", + }, + }, + expPollStatus: group.PollStatusSubmitted, + }, + "skip already voted": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotes, + Expiry: *voteExpiry, + AggSig: sigma, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + votes: validVotesSkip, + doBefore: func(ctx context.Context) { + _, err := s.msgClient.VotePoll(ctx, &group.MsgVotePoll{ + PollId: myPollID, + Voter: s.addrBls1.String(), + Options: group.Options{Titles: []string{"charlie"}}, + }) + s.Require().NoError(err) + }, + expVoteState: group.TallyPoll{ + Counts: map[string]string{ + "alice": "3", + "bob": "0", + "charlie": "1", + }, + }, + expPollStatus: group.PollStatusSubmitted, + }, + "on vote expiry": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotes, + Expiry: *voteExpiry, + AggSig: sigma, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + srcCtx: s.sdkCtx.WithBlockTime(s.blockTime.Add(time.Second * 15)), + expErr: true, + }, + "on vote late": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotesLate, + Expiry: *voteExpiryLate, + AggSig: sigmaLate, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + srcCtx: s.sdkCtx.WithBlockTime(s.blockTime.Add(time.Second * 35)), + expErr: true, + }, + "on vote limit": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotesLong, + Expiry: *voteExpiry, + AggSig: sigmaLong, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + expErr: true, + }, + "on vote option": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotesInvalid, + Expiry: *voteExpiry, + AggSig: sigmaInvalid, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + expErr: true, + }, + "on poll expiry": { + req: &group.MsgVotePollAgg{ + Sender: s.addr1.String(), + PollId: myPollID, + Votes: sortedVotesLate, + Expiry: *voteExpiryLate, + AggSig: sigmaLate, + Metadata: []byte(fmt.Sprintf("aggregated votes submitted by %s", s.addr1.String())), + }, + srcCtx: s.sdkCtx.WithBlockTime(s.blockTime.Add(time.Second * 25)), + expErr: true, + }, + } + + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + sdkCtx := s.sdkCtx + if !spec.srcCtx.IsZero() { + sdkCtx = spec.srcCtx + } + sdkCtx, _ = sdkCtx.CacheContext() + ctx := types.Context{Context: sdkCtx} + + if spec.doBefore != nil { + spec.doBefore(ctx) + } + _, err := s.msgClient.VotePollAgg(ctx, spec.req) + if spec.expErr { + s.Require().Error(err) + return + } + s.Require().NoError(err) + + // query votes by poll + votesByPollRes, err := s.queryClient.VotesForPollByPoll(ctx, &group.QueryVotesForPollByPollRequest{ + PollId: myPollID, + }) + s.Require().NoError(err) + votesByPoll := votesByPollRes.Votes + s.Require().Equal(len(spec.votes), len(votesByPoll)) + + for i, vote := range votesByPoll { + s.Assert().Equal(spec.req.PollId, vote.PollId) + s.Assert().Equal(spec.votes[i].Address, vote.Voter) + s.Assert().Equal(spec.votes[i].Options.Titles, vote.Options.Titles) + submittedAt, err = gogotypes.TimestampFromProto(&vote.SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + } + + // query votes by voter + for _, vote := range spec.votes { + votesByVoterRes, err := s.queryClient.VotesForPollByVoter(ctx, &group.QueryVotesForPollByVoterRequest{ + Voter: vote.Address, + }) + s.Require().NoError(err) + votesByVoter := votesByVoterRes.Votes + s.Require().Equal(1, len(votesByVoter)) + s.Assert().Equal(spec.req.PollId, votesByVoter[0].PollId) + s.Assert().Equal(vote.Address, votesByVoter[0].Voter) + s.Assert().Equal(vote.Options.Titles, votesByVoter[0].Options.Titles) + submittedAt, err = gogotypes.TimestampFromProto(&votesByVoter[0].SubmittedAt) + s.Require().NoError(err) + s.Assert().Equal(s.blockTime, submittedAt) + } + + // and poll is updated + pollRes, err := s.queryClient.Poll(ctx, &group.QueryPollRequest{ + PollId: spec.req.PollId, + }) + s.Require().NoError(err) + poll := pollRes.Poll + s.Assert().Equal(spec.expVoteState, poll.VoteState) + s.Assert().Equal(spec.expPollStatus, poll.Status) + }) + } +} + +func createProposal( + ctx context.Context, s *IntegrationTestSuite, msgs []sdk.Msg, + proposers []string) uint64 { + proposalReq := &group.MsgCreateProposal{ + Address: s.groupAccountAddr.String(), + Proposers: proposers, + Metadata: nil, + } + err := proposalReq.SetMsgs(msgs) + s.Require().NoError(err) + + proposalRes, err := s.msgClient.CreateProposal(ctx, proposalReq) + s.Require().NoError(err) + return proposalRes.ProposalId +} + +func createProposalAndVote( + ctx context.Context, s *IntegrationTestSuite, msgs []sdk.Msg, + proposers []string, choice group.Choice) uint64 { + s.Require().Greater(len(proposers), 0) + myProposalID := createProposal(ctx, s, msgs, proposers) + + _, err := s.msgClient.Vote(ctx, &group.MsgVote{ + ProposalId: myProposalID, + Voter: proposers[0], + Choice: choice, + }) + s.Require().NoError(err) + return myProposalID +} + +func createGroupAndGroupAccount( + admin sdk.AccAddress, + s *IntegrationTestSuite, +) (string, uint64, group.DecisionPolicy, []byte) { + groupRes, err := s.msgClient.CreateGroup(s.ctx, &group.MsgCreateGroup{ + Admin: admin.String(), + Members: nil, + Metadata: nil, + }) + s.Require().NoError(err) + + myGroupID := groupRes.GroupId + groupAccount := &group.MsgCreateGroupAccount{ + Admin: admin.String(), + GroupId: myGroupID, + Metadata: nil, + } + + policy := group.NewThresholdDecisionPolicy( + "1", + gogotypes.Duration{Seconds: 1}, + ) + err = groupAccount.SetDecisionPolicy(policy) + s.Require().NoError(err) + + groupAccountRes, err := s.msgClient.CreateGroupAccount(s.ctx, groupAccount) + s.Require().NoError(err) + + res, err := s.queryClient.GroupAccountInfo(s.ctx, &group.QueryGroupAccountInfoRequest{Address: groupAccountRes.Address}) + s.Require().NoError(err) + + return groupAccountRes.Address, myGroupID, policy, res.Info.DerivationKey +} diff --git a/x/group/sigverify.go b/x/group/sigverify.go new file mode 100644 index 0000000000..2efcbcc211 --- /dev/null +++ b/x/group/sigverify.go @@ -0,0 +1,22 @@ +package group + +import ( + "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +func VerifyAggregateSignature(msgs [][]byte, msgCheck bool, sig []byte, pkss [][]cryptotypes.PubKey) error { + pkssBls := make([][]*bls12381.PubKey, len(pkss)) + for i, pks := range pkss { + for _, pk := range pks { + pkBls, ok := pk.(*bls12381.PubKey) + if !ok { + return sdkerrors.Wrap(sdkerrors.ErrInvalidPubKey, "only support bls public key") + } + pkssBls[i] = append(pkssBls[i], pkBls) + } + } + + return bls12381.VerifyAggregateSignature(msgs, msgCheck, sig, pkssBls) +} diff --git a/x/group/simulation/genesis.go b/x/group/simulation/genesis.go new file mode 100644 index 0000000000..5c7cafea35 --- /dev/null +++ b/x/group/simulation/genesis.go @@ -0,0 +1,197 @@ +package simulation + +import ( + "math/rand" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + gogotypes "github.com/gogo/protobuf/types" + + "github.com/cosmos/cosmos-sdk/x/group" +) + +const ( + GroupInfo = "group-info" + GroupMembers = "group-members" + GroupAccountInfo = "group-accout-info" + GroupProposals = "group-proposals" + GroupVote = "group-vote" +) + +func getGroups(r *rand.Rand, accounts []simtypes.Account) []*group.GroupInfo { + groups := make([]*group.GroupInfo, 3) + for i := 0; i < 3; i++ { + acc, _ := simtypes.RandomAcc(r, accounts) + groups[i] = &group.GroupInfo{ + GroupId: uint64(i + 1), + Admin: acc.Address.String(), + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + Version: 1, + TotalWeight: "10", + } + } + return groups +} + +func getGroupMembers(r *rand.Rand, accounts []simtypes.Account) []*group.GroupMember { + groupMembers := make([]*group.GroupMember, 3) + for i := 0; i < 3; i++ { + acc, _ := simtypes.RandomAcc(r, accounts) + groupMembers[i] = &group.GroupMember{ + GroupId: uint64(i + 1), + Member: &group.Member{ + Address: acc.Address.String(), + Weight: "10", + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + }, + } + } + return groupMembers +} + +func getGroupAccounts(r *rand.Rand, simState *module.SimulationState) []*group.GroupAccountInfo { + groupAccounts := make([]*group.GroupAccountInfo, 3) + for i := 0; i < 3; i++ { + acc, _ := simtypes.RandomAcc(r, simState.Accounts) + any, err := codectypes.NewAnyWithValue(group.NewThresholdDecisionPolicy("10", gogotypes.Duration{Seconds: 1})) + if err != nil { + panic(err) + } + groupAccounts[i] = &group.GroupAccountInfo{ + GroupId: uint64(i + 1), + Admin: acc.Address.String(), + Address: acc.Address.String(), + Version: 1, + DecisionPolicy: any, + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + DerivationKey: []byte(simtypes.RandStringOfLength(r, 10)), + } + } + return groupAccounts +} + +func getProposals(r *rand.Rand, simState *module.SimulationState) []*group.Proposal { + proposals := make([]*group.Proposal, 3) + proposers := []string{simState.Accounts[0].Address.String(), simState.Accounts[1].Address.String()} + for i := 0; i < 3; i++ { + from, _ := simtypes.RandomAcc(r, simState.Accounts) + to, _ := simtypes.RandomAcc(r, simState.Accounts) + fromAddr := from.Address.String() + + proposal := &group.Proposal{ + ProposalId: uint64(i + 1), + Proposers: proposers, + Address: fromAddr, + GroupVersion: uint64(i + 1), + GroupAccountVersion: uint64(i + 1), + Status: group.ProposalStatusSubmitted, + Result: group.ProposalResultAccepted, + VoteState: group.Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "0", + }, + ExecutorResult: group.ProposalExecutorResultNotRun, + Metadata: []byte(simtypes.RandStringOfLength(r, 50)), + SubmittedAt: gogotypes.Timestamp{Seconds: 1}, + Timeout: gogotypes.Timestamp{Seconds: 1000}, + } + err := proposal.SetMsgs([]sdk.Msg{&banktypes.MsgSend{ + FromAddress: fromAddr, + ToAddress: to.Address.String(), + Amount: sdk.NewCoins(sdk.NewInt64Coin("test", 10)), + }}) + if err != nil { + panic(err) + } + + proposals[i] = proposal + } + + return proposals +} + +func getVotes(r *rand.Rand, simState *module.SimulationState) []*group.Vote { + votes := make([]*group.Vote, 3) + + for i := 0; i < 3; i++ { + votes[i] = &group.Vote{ + ProposalId: uint64(i + 1), + Voter: simState.Accounts[i].Address.String(), + Choice: getVoteChoice(i), + Metadata: []byte(simtypes.RandStringOfLength(r, 50)), + SubmittedAt: gogotypes.Timestamp{Seconds: 10}, + } + } + + return votes +} + +func getVoteChoice(index int) group.Choice { + switch index { + case 0: + return group.Choice_CHOICE_YES + case 1: + return group.Choice_CHOICE_NO + case 2: + return group.Choice_CHOICE_ABSTAIN + default: + return group.Choice_CHOICE_VETO + } +} + +// RandomizedGenState generates a random GenesisState for the group module. +func RandomizedGenState(simState *module.SimulationState) { + + // groups + var groups []*group.GroupInfo + simState.AppParams.GetOrGenerate( + simState.Cdc, GroupInfo, &groups, simState.Rand, + func(r *rand.Rand) { groups = getGroups(r, simState.Accounts) }, + ) + + // group members + var members []*group.GroupMember + simState.AppParams.GetOrGenerate( + simState.Cdc, GroupMembers, &members, simState.Rand, + func(r *rand.Rand) { members = getGroupMembers(r, simState.Accounts) }, + ) + + // group accounts + var groupAccounts []*group.GroupAccountInfo + simState.AppParams.GetOrGenerate( + simState.Cdc, GroupAccountInfo, &groupAccounts, simState.Rand, + func(r *rand.Rand) { groupAccounts = getGroupAccounts(r, simState) }, + ) + + // proposals + var proposals []*group.Proposal + simState.AppParams.GetOrGenerate( + simState.Cdc, GroupProposals, &proposals, simState.Rand, + func(r *rand.Rand) { proposals = getProposals(r, simState) }, + ) + + // votes + var votes []*group.Vote + simState.AppParams.GetOrGenerate( + simState.Cdc, GroupVote, &votes, simState.Rand, + func(r *rand.Rand) { votes = getVotes(r, simState) }, + ) + + groupGenesis := group.GenesisState{ + GroupSeq: 3, + Groups: groups, + GroupMembers: members, + GroupAccountSeq: 3, + GroupAccounts: groupAccounts, + ProposalSeq: 3, + Proposals: proposals, + Votes: votes, + } + + simState.GenState[group.ModuleName] = simState.Cdc.MustMarshalJSON(&groupGenesis) +} diff --git a/x/group/simulation/operations.go b/x/group/simulation/operations.go new file mode 100644 index 0000000000..7be162cd79 --- /dev/null +++ b/x/group/simulation/operations.go @@ -0,0 +1,933 @@ +package simulation + +import ( + "fmt" + "math/rand" + "strings" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/simapp/helpers" + simappparams "github.com/cosmos/cosmos-sdk/simapp/params" + sdk "github.com/cosmos/cosmos-sdk/types" + simtypes "github.com/cosmos/cosmos-sdk/types/simulation" + "github.com/cosmos/cosmos-sdk/x/simulation" + gogotypes "github.com/gogo/protobuf/types" + + regentypes "github.com/cosmos/cosmos-sdk/regen/types" + "github.com/cosmos/cosmos-sdk/x/group" + "github.com/cosmos/cosmos-sdk/x/group/exported" +) + +// group message types +var ( + TypeMsgCreateGroup = sdk.MsgTypeURL(&group.MsgCreateGroup{}) + TypeMsgUpdateGroupMembers = sdk.MsgTypeURL(&group.MsgUpdateGroupMembers{}) + TypeMsgUpdateGroupAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupAdmin{}) + TypeMsgUpdateGroupMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupMetadata{}) + TypeMsgCreateGroupAccount = sdk.MsgTypeURL(&group.MsgCreateGroupAccount{}) + TypeMsgUpdateGroupAccountAdmin = sdk.MsgTypeURL(&group.MsgUpdateGroupAccountAdmin{}) + TypeMsgUpdateGroupAccountDecisionPolicy = sdk.MsgTypeURL(&group.MsgUpdateGroupAccountDecisionPolicy{}) + TypeMsgUpdateGroupAccountMetadata = sdk.MsgTypeURL(&group.MsgUpdateGroupAccountMetadata{}) + TypeMsgCreateProposal = sdk.MsgTypeURL(&group.MsgCreateProposal{}) + TypeMsgVote = sdk.MsgTypeURL(&group.MsgVote{}) + TypeMsgExec = sdk.MsgTypeURL(&group.MsgExec{}) +) + +// Simulation operation weights constants +const ( + OpMsgCreateGroup = "op_weight_msg_create_group" + OpMsgUpdateGroupAdmin = "op_weight_msg_update_group_admin" + OpMsgUpdateGroupMetadata = "op_wieght_msg_update_group_metadata" + OpMsgUpdateGroupMembers = "op_weight_msg_update_group_members" + OpMsgCreateGroupAccountRequest = "op_weight_msg_create_group_account" + OpMsgUpdateGroupAccountAdmin = "op_weight_msg_update_group_account_admin" + OpMsgUpdateGroupAccountDecisionPolicy = "op_weight_msg_update_group_account_decision_policy" + OpMsgUpdateGroupAccountMetaData = "op_weight_msg_update_group_account_metadata" + OpMsgCreateProposal = "op_weight_msg_create_proposal" + OpMsgVote = "op_weight_msg_vote" + OpMsgExec = "ops_weight_msg_exec" +) + +// If update group or group account txn's executed, `SimulateMsgVote` & `SimulateMsgExec` txn's returns `noOp`. +// That's why we have less weight for update group & group-account txn's. +const ( + WeightCreateGroup = 100 + WeightCreateGroupAccount = 100 + WeightCreateProposal = 90 + WeightMsgVote = 90 + WeightMsgExec = 90 + WeightUpdateGroupMetadata = 5 + WeightUpdateGroupAdmin = 5 + WeightUpdateGroupMembers = 5 + WeightUpdateGroupAccountAdmin = 5 + WeightUpdateGroupAccountDecisionPolicy = 5 + WeightUpdateGroupAccountMetadata = 5 + GroupMemberWeight = 40 +) + +// WeightedOperations returns all the operations from the module with their respective weights +func WeightedOperations( + appParams simtypes.AppParams, cdc codec.JSONCodec, ak exported.AccountKeeper, + bk exported.BankKeeper, qryClient group.QueryClient, protoCdc *codec.ProtoCodec) simulation.WeightedOperations { + var ( + weightMsgCreateGroup int + weightMsgUpdateGroupAdmin int + weightMsgUpdateGroupMetadata int + weightMsgUpdateGroupMembers int + weightMsgCreateGroupAccount int + weightMsgUpdateGroupAccountAdmin int + weightMsgUpdateGroupAccountDecisionPolicy int + weightMsgUpdateGroupAccountMetadata int + weightMsgCreateProposal int + weightMsgVote int + weightMsgExec int + ) + + appParams.GetOrGenerate(cdc, OpMsgCreateGroup, &weightMsgCreateGroup, nil, + func(_ *rand.Rand) { + weightMsgCreateGroup = WeightCreateGroup + }, + ) + appParams.GetOrGenerate(cdc, OpMsgCreateGroupAccountRequest, &weightMsgCreateGroupAccount, nil, + func(_ *rand.Rand) { + weightMsgCreateGroupAccount = WeightCreateGroupAccount + }, + ) + appParams.GetOrGenerate(cdc, OpMsgCreateProposal, &weightMsgCreateProposal, nil, + func(_ *rand.Rand) { + weightMsgCreateProposal = WeightCreateProposal + }, + ) + appParams.GetOrGenerate(cdc, OpMsgVote, &weightMsgVote, nil, + func(_ *rand.Rand) { + weightMsgVote = WeightMsgVote + }, + ) + appParams.GetOrGenerate(cdc, OpMsgExec, &weightMsgExec, nil, + func(_ *rand.Rand) { + weightMsgExec = WeightMsgExec + }, + ) + appParams.GetOrGenerate(cdc, OpMsgUpdateGroupMetadata, &weightMsgUpdateGroupMetadata, nil, + func(_ *rand.Rand) { + weightMsgUpdateGroupMetadata = WeightUpdateGroupMetadata + }, + ) + appParams.GetOrGenerate(cdc, OpMsgUpdateGroupAdmin, &weightMsgUpdateGroupAdmin, nil, + func(_ *rand.Rand) { + weightMsgUpdateGroupAdmin = WeightUpdateGroupAdmin + }, + ) + appParams.GetOrGenerate(cdc, OpMsgUpdateGroupMembers, &weightMsgUpdateGroupMembers, nil, + func(_ *rand.Rand) { + weightMsgUpdateGroupMembers = WeightUpdateGroupMembers + }, + ) + appParams.GetOrGenerate(cdc, OpMsgUpdateGroupAccountAdmin, &weightMsgUpdateGroupAccountAdmin, nil, + func(_ *rand.Rand) { + weightMsgUpdateGroupAccountAdmin = WeightUpdateGroupAccountAdmin + }, + ) + appParams.GetOrGenerate(cdc, OpMsgUpdateGroupAccountDecisionPolicy, &weightMsgUpdateGroupAccountDecisionPolicy, nil, + func(_ *rand.Rand) { + weightMsgUpdateGroupAccountDecisionPolicy = WeightUpdateGroupAccountDecisionPolicy + }, + ) + appParams.GetOrGenerate(cdc, OpMsgUpdateGroupAccountMetaData, &weightMsgUpdateGroupAccountMetadata, nil, + func(_ *rand.Rand) { + weightMsgUpdateGroupAccountMetadata = WeightUpdateGroupAccountMetadata + }, + ) + + return simulation.WeightedOperations{ + simulation.NewWeightedOperation( + weightMsgCreateGroup, + SimulateMsgCreateGroup(ak, bk, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgCreateGroupAccount, + SimulateMsgCreateGroupAccount(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgCreateProposal, + SimulateMsgCreateProposal(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgVote, + SimulateMsgVote(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgExec, + SimulateMsgExec(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgUpdateGroupMetadata, + SimulateMsgUpdateGroupMetadata(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgUpdateGroupAdmin, + SimulateMsgUpdateGroupAdmin(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgUpdateGroupMembers, + SimulateMsgUpdateGroupMembers(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgUpdateGroupAccountAdmin, + SimulateMsgUpdateGroupAccountAdmin(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgUpdateGroupAccountDecisionPolicy, + SimulateMsgUpdateGroupAccountDecisionPolicy(ak, bk, qryClient, protoCdc), + ), + simulation.NewWeightedOperation( + weightMsgUpdateGroupAccountMetadata, + SimulateMsgUpdateGroupAccountMetadata(ak, bk, qryClient, protoCdc), + ), + } +} + +// SimulateMsgCreateGroup generates a MsgCreateGroup with random values +func SimulateMsgCreateGroup(ak exported.AccountKeeper, bk exported.BankKeeper, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc, _ := simtypes.RandomAcc(r, accounts) + account := ak.GetAccount(ctx, acc.Address) + accAddr := acc.Address.String() + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "fee error"), nil, err + } + + members := []group.Member{ + { + Address: accAddr, + Weight: fmt.Sprintf("%d", GroupMemberWeight), + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + }, + } + + msg := &group.MsgCreateGroup{Admin: accAddr, Members: members, Metadata: []byte(simtypes.RandStringOfLength(r, 10))} + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroup, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgCreateGroupAccount generates a NewMsgCreateGroupAccount with random values +func SimulateMsgCreateGroupAccount(ak exported.AccountKeeper, bk exported.BankKeeper, qryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc := accounts[0] + account := ak.GetAccount(ctx, acc.Address) + + spendableCoins := bk.SpendableCoins(ctx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, ctx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, "fee error"), nil, err + } + + groupAdmin, groupID, op, err := getGroupDetails(ctx, qryClient, acc) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + addr, err := sdk.AccAddressFromBech32(groupAdmin) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, "fail to decode acc address"), nil, err + } + + msg, err := group.NewMsgCreateGroupAccount( + addr, + groupID, + []byte(simtypes.RandStringOfLength(r, 10)), + &group.ThresholdDecisionPolicy{ + Threshold: "20", + Timeout: gogotypes.Duration{Seconds: int64(30 * 24 * 60 * 60)}, + }, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, err.Error()), nil, err + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(msg, true, "", protoCdc), nil, err + } +} + +func getGroupDetails(sdkCtx sdk.Context, qryClient group.QueryClient, acc simtypes.Account) (groupAdmin string, groupID uint64, op simtypes.OperationMsg, err error) { + ctx := regentypes.Context{Context: sdkCtx} + + groups, err := qryClient.GroupsByAdmin(ctx, &group.QueryGroupsByAdminRequest{Admin: acc.Address.String()}) + if err != nil { + return "", 0, simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, "fail to query groups"), err + } + + if len(groups.Groups) == 0 { + return "", 0, simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, ""), nil + } + + groupAdmin = groups.Groups[0].Admin + groupID = groups.Groups[0].GroupId + + return groupAdmin, groupID, simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateGroupAccount, ""), nil +} + +// SimulateMsgCreateProposal generates a NewMsgCreateProposal with random values +func SimulateMsgCreateProposal(ak exported.AccountKeeper, bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc := accounts[0] + account := ak.GetAccount(sdkCtx, acc.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "fee error"), nil, err + } + + ctx := regentypes.Context{Context: sdkCtx} + groupAdmin, _, op, err := getGroupDetails(sdkCtx, queryClient, acc) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, opMsg), nil, err + } + + msg := group.MsgCreateProposal{ + Address: groupAccounts[0].Address, + Proposers: []string{acc.Address.String()}, + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgCreateProposal, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgUpdateGroupAdmin generates a MsgUpdateGroupAccountAdmin with random values +func SimulateMsgUpdateGroupAdmin(ak exported.AccountKeeper, bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + acc2 := accounts[1] + + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "fee error"), nil, err + } + + ctx := regentypes.Context{Context: sdkCtx} + + groupAdmin, groupID, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, opMsg), nil, err + } + + msg := group.MsgUpdateGroupAdmin{ + GroupId: groupID, + Admin: groupAccounts[0].Admin, + NewAdmin: acc2.Address.String(), + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAdmin, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgUpdateGroupMetadata generates a MsgUpdateGroupMetadata with random values +func SimulateMsgUpdateGroupMetadata(ak exported.AccountKeeper, bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc := accounts[0] + account := ak.GetAccount(sdkCtx, acc.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "fee error"), nil, err + } + + groupAdmin, groupID, op, err := getGroupDetails(sdkCtx, queryClient, acc) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + msg := group.MsgUpdateGroupMetadata{ + GroupId: groupID, + Admin: groupAdmin, + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMetadata, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgUpdateGroupMembers generates a MsgUpdateGroupMembers with random values +func SimulateMsgUpdateGroupMembers(ak exported.AccountKeeper, + bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + acc2 := accounts[1] + acc3 := accounts[2] + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "fee error"), nil, err + } + + ctx := regentypes.Context{Context: sdkCtx} + groupAdmin, groupID, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, opMsg), nil, err + } + + members := []group.Member{ + { + Address: acc2.Address.String(), + Weight: fmt.Sprintf("%d", GroupMemberWeight), + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + }, + { + Address: acc3.Address.String(), + Weight: fmt.Sprintf("%d", GroupMemberWeight), + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + }, + } + + msg := group.MsgUpdateGroupMembers{ + GroupId: groupID, + Admin: groupAdmin, + MemberUpdates: members, + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupMembers, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgUpdateGroupAccountAdmin generates a MsgUpdateGroupAccountAdmin with random values +func SimulateMsgUpdateGroupAccountAdmin(ak exported.AccountKeeper, bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + acc2 := accounts[1] + + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountAdmin, "fee error"), nil, err + } + + ctx := regentypes.Context{Context: sdkCtx} + + groupAdmin, _, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountAdmin, opMsg), nil, err + } + + msg := group.MsgUpdateGroupAccountAdmin{ + Admin: groupAccounts[0].Admin, + Address: groupAccounts[0].Address, + NewAdmin: acc2.Address.String(), + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountAdmin, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgUpdateGroupAccountDecisionPolicy generates a NewMsgUpdateGroupAccountDecisionPolicyRequest with random values +func SimulateMsgUpdateGroupAccountDecisionPolicy(ak exported.AccountKeeper, + bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountDecisionPolicy, "fee error"), nil, err + } + + ctx := regentypes.Context{Context: sdkCtx} + groupAdmin, _, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountDecisionPolicy, opMsg), nil, err + } + + adminBech32, err := sdk.AccAddressFromBech32(groupAccounts[0].Admin) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountDecisionPolicy, fmt.Sprintf("fail to decide bech32 address: %s", err.Error())), nil, nil + } + + groupAccountBech32, err := sdk.AccAddressFromBech32(groupAccounts[0].Address) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountDecisionPolicy, fmt.Sprintf("fail to decide bech32 address: %s", err.Error())), nil, nil + } + + msg, err := group.NewMsgUpdateGroupAccountDecisionPolicyRequest(adminBech32, groupAccountBech32, &group.ThresholdDecisionPolicy{ + Threshold: fmt.Sprintf("%d", simtypes.RandIntBetween(r, 1, 20)), + Timeout: gogotypes.Duration{Seconds: int64(simtypes.RandIntBetween(r, 100, 1000))}, + }) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountDecisionPolicy, err.Error()), nil, err + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountDecisionPolicy, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgUpdateGroupAccountMetadata generates a MsgUpdateGroupAccountMetadata with random values +func SimulateMsgUpdateGroupAccountMetadata(ak exported.AccountKeeper, + bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountMetadata, "fee error"), nil, err + } + + ctx := regentypes.Context{Context: sdkCtx} + groupAdmin, _, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountMetadata, opMsg), nil, err + } + + msg := group.MsgUpdateGroupAccountMetadata{ + Admin: groupAccounts[0].Admin, + Address: groupAccounts[0].Address, + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + } + + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountMetadata, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgVote generates a MsgVote with random values +func SimulateMsgVote(ak exported.AccountKeeper, + bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fee error"), nil, err + } + ctx := regentypes.Context{Context: sdkCtx} + groupAdmin, _, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, opMsg), nil, err + } + + proposalsResult, err := queryClient.ProposalsByGroupAccount(ctx, &group.QueryProposalsByGroupAccountRequest{Address: groupAccounts[0].Address}) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fail to query group info"), nil, err + } + proposals := proposalsResult.GetProposals() + if len(proposals) == 0 { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil + } + + proposalID := -1 + + for _, proposal := range proposals { + if proposal.Status == group.ProposalStatusSubmitted { + votingPeriodEnd, err := gogotypes.TimestampFromProto(&proposal.Timeout) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "error: while converting to timestamp"), nil, err + } + proposalID = int(proposal.ProposalId) + if votingPeriodEnd.Before(ctx.BlockTime()) || votingPeriodEnd.Equal(ctx.BlockTime()) { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "voting period ended: skipping"), nil, nil + } + break + } + } + + // return no-op if no proposal found + if proposalID == -1 { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil + } + + msg := group.MsgVote{ + ProposalId: uint64(proposalID), + Voter: acc1.Address.String(), + Choice: group.Choice_CHOICE_YES, + Metadata: []byte(simtypes.RandStringOfLength(r, 10)), + } + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountMetadata, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + + if err != nil { + if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group account was modified") { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "no-op:group/group-account was modified"), nil, nil + } + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +// SimulateMsgExec generates a MsgExec with random values +func SimulateMsgExec(ak exported.AccountKeeper, + bk exported.BankKeeper, queryClient group.QueryClient, protoCdc *codec.ProtoCodec) simtypes.Operation { + return func( + r *rand.Rand, app *baseapp.BaseApp, sdkCtx sdk.Context, accounts []simtypes.Account, chainID string) (simtypes.OperationMsg, []simtypes.FutureOperation, error) { + acc1 := accounts[0] + + account := ak.GetAccount(sdkCtx, acc1.Address) + + spendableCoins := bk.SpendableCoins(sdkCtx, account.GetAddress()) + fees, err := simtypes.RandomFees(r, sdkCtx, spendableCoins) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fee error"), nil, err + } + ctx := regentypes.Context{Context: sdkCtx} + groupAdmin, _, op, err := getGroupDetails(sdkCtx, queryClient, acc1) + if err != nil { + return op, nil, err + } + if groupAdmin == "" { + return op, nil, nil + } + + groupAccounts, opMsg, err := groupAccountsByAdmin(ctx, queryClient, groupAdmin) + if groupAccounts == nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, opMsg), nil, err + } + + proposalsResult, err := queryClient.ProposalsByGroupAccount(ctx, &group.QueryProposalsByGroupAccountRequest{Address: groupAccounts[0].Address}) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "fail to query group info"), nil, err + } + proposals := proposalsResult.GetProposals() + if len(proposals) == 0 { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil + } + + proposalID := -1 + + for _, proposal := range proposals { + if proposal.Status == group.ProposalStatusSubmitted { + proposalID = int(proposal.ProposalId) + break + } + } + + // return no-op if no proposal found + if proposalID == -1 { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgVote, "no proposals found"), nil, nil + } + + msg := group.MsgExec{ + ProposalId: uint64(proposalID), + Signer: acc1.Address.String(), + } + txGen := simappparams.MakeTestEncodingConfig().TxConfig + tx, err := helpers.GenTx( + txGen, + []sdk.Msg{&msg}, + fees, + helpers.DefaultGenTxGas, + chainID, + []uint64{account.GetAccountNumber()}, + []uint64{account.GetSequence()}, + acc1.PrivKey, + ) + if err != nil { + return simtypes.NoOpMsg(group.ModuleName, TypeMsgUpdateGroupAccountMetadata, "unable to generate mock tx"), nil, err + } + + _, _, err = app.Deliver(txGen.TxEncoder(), tx) + if err != nil { + if strings.Contains(err.Error(), "group was modified") || strings.Contains(err.Error(), "group account was modified") { + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "no-op:group/group-account was modified"), nil, nil + } + return simtypes.NoOpMsg(group.ModuleName, msg.Type(), "unable to deliver tx"), nil, err + } + + return simtypes.NewOperationMsg(&msg, true, "", protoCdc), nil, err + } +} + +func groupAccountsByAdmin(ctx regentypes.Context, qryClient group.QueryClient, admin string) ([]*group.GroupAccountInfo, string, error) { + result, err := qryClient.GroupAccountsByAdmin(ctx, &group.QueryGroupAccountsByAdminRequest{Admin: admin}) + if err != nil { + return nil, "fail to query group info", err + } + + groupAccounts := result.GetGroupAccounts() + if len(groupAccounts) == 0 { + return nil, "no group account found", nil + } + return groupAccounts, "", nil +} diff --git a/x/group/spec/01_concepts.md b/x/group/spec/01_concepts.md new file mode 100644 index 0000000000..8400a2eec0 --- /dev/null +++ b/x/group/spec/01_concepts.md @@ -0,0 +1,74 @@ + + +# Concepts + +## Group + +A group is simply an aggregation of accounts with associated weights. It is not +an account and doesn't have a balance. It doesn't in and of itself have any +sort of voting or decision weight. It does have an "administrator" which has +the ability to add, remove and update members in the group. Note that a +group account could be an administrator of a group. + +## Group Account + +A group account is an account associated with a group and a decision policy. +Group accounts are abstracted from groups because a single group may have +multiple decision policies for different types of actions. Managing group +membership separately from decision policies results in the least overhead +and keeps membership consistent across different policies. The pattern that +is recommended is to have a single master group account for a given group, +and then to create separate group accounts with different decision policies +and delegate the desired permissions from the master account to +those "sub-accounts" using the `x/authz` module. + +## Decision Policy + +A decision policy is the mechanism by which members of a group can vote on +proposals. + +All decision policies generally would have a minimum and maximum voting window. +The minimum voting window is the minimum amount of time that must pass in order +for a proposal to potentially pass, and it may be set to 0. The maximum voting +window is the maximum time that a proposal may be voted on before it is closed. +Both of these values must be less than a chain-wide max voting window parameter. + +### Threshold decision policy + +A threshold decision policy defines a threshold of yes votes (based on a tally +of voter weights) that must be achieved in order for a proposal to pass. For +this decision policy, abstain and veto are simply treated as no's. + +## Proposal + +Any member of a group can submit a proposal for a group account to decide upon. +A proposal consists of a set of messages that will be executed if the proposal +passes as well as any metadata associated with the proposal. + +## Voting + +There are four choices to choose while voting - yes, no, abstain and veto. Not +all decision policies will support them. Votes can contain some optional metadata. +During the voting window, accounts that have already voted may change their vote. +In the current implementation, the voting window begins as soon as a proposal +is submitted. + +## Executing Proposals + +Proposals will not be automatically executed by the chain in this current design, +but rather a user must submit a `Msg/Exec` transaction to attempt to execute the +proposal based on the current votes and decision policy. +It's also possible to try to execute a proposal immediately on creation or on +new votes using the `Exec` field of `Msg/CreateProposal` and `Msg/Vote` requests. +In the former case, proposers signatures are considered as yes votes. +For now, if the proposal can't be executed, it'll still be opened for new votes and +could be executed later on. + +### Changing Group Membership + +In the current implementation, changing a group's membership (adding or removing members or changing their weight) +will cause all existing proposals for group accounts linked to this group +to be invalidated. They will simply fail if someone calls `Msg/Exec` and will +eventually be garbage collected. \ No newline at end of file diff --git a/x/group/spec/02_state.md b/x/group/spec/02_state.md new file mode 100644 index 0000000000..b9607e22f5 --- /dev/null +++ b/x/group/spec/02_state.md @@ -0,0 +1,104 @@ + + +# State + +The `group` module uses the `orm` package which provides table storage with support for +primary keys and secondary indexes. `orm` also defines `Sequence` which is a persistent unique key generator based on a counter that can be used along with `Table`s. + +Here's the list of tables and associated sequences and indexes stored as part of the `group` module. + +## Group Table + +The `groupTable` stores `GroupInfo`: `0x0 | []byte(GroupId) -> ProtocolBuffer(GroupInfo)`. + +### groupSeq + +The value of `groupSeq` is incremented when creating a new group and corresponds to the new `GroupId`: `0x1 | 0x1 -> BigEndian`. + +The second `0x1` corresponds to the ORM `sequenceStorageKey`. + +### groupByAdminIndex + +`groupByAdminIndex` allows to retrieve groups by admin address: +`0x2 | []byte(group.Admin) | []byte(GroupId) -> []byte()`. + +## Group Member Table + +The `groupMemberTable` stores `GroupMember`s: `0x10 | []byte(GroupId) | []byte(member.Address) -> ProtocolBuffer(GroupMember)`. + +The `groupMemberTable` is a primary key table and its `PrimaryKey` is given by +`[]byte(GroupId) | []byte(member.Address)` which is used by the following indexes. + +### groupMemberByGroupIndex + +`groupMemberByGroupIndex` allows to retrieve group members by group id: +`0x11 | []byte(GroupId) | PrimaryKey | byte(len(PrimaryKey)) -> []byte()`. + +### groupMemberByMemberIndex + +`groupMemberByMemberIndex` allows to retrieve group members by member address: +`0x12 | []byte(member.Address) | PrimaryKey | byte(len(PrimaryKey)) -> []byte()`. + +## Group Account Table + +The `groupAccountTable` stores `GroupAccountInfo`: `0x20 | []byte(Address) -> ProtocolBuffer(GroupAccountInfo)`. + +The `groupAccountTable` is a primary key table and its `PrimaryKey` is given by +`[]byte(Address)` which is used by the following indexes. + +### groupAccountSeq + +The value of `groupAccountSeq` is incremented when creating a new group account and is used to generate the new group account `Address`: +`0x21 | 0x1 -> BigEndian`. + +The second `0x1` corresponds to the ORM `sequenceStorageKey`. + +### groupAccountByGroupIndex + +`groupAccountByGroupIndex` allows to retrieve group accounts by group id: +`0x22 | []byte(GroupId) | PrimaryKey | byte(len(PrimaryKey)) -> []byte()`. + +### groupAccountByAdminIndex + +`groupAccountByAdminIndex` allows to retrieve group accounts by admin address: +`0x23 | []byte(Address) | PrimaryKey | byte(len(PrimaryKey)) -> []byte()`. + +## Proposal Table + +The `proposalTable` stores `Proposal`s: `0x30 | []byte(ProposalId) -> ProtocolBuffer(Proposal)`. + +### proposalSeq + +The value of `proposalSeq` is incremented when creating a new proposal and corresponds to the new `ProposalId`: `0x31 | 0x1 -> BigEndian`. + +The second `0x1` corresponds to the ORM `sequenceStorageKey`. + +### proposalByGroupAccountIndex + +`proposalByGroupAccountIndex` allows to retrieve proposals by group account address: +`0x32 | []byte(account.Address) | []byte(ProposalId) -> []byte()`. + +### proposalByProposerIndex + +`proposalByProposerIndex` allows to retrieve proposals by proposer address: +`0x33 | []byte(proposer.Address) | []byte(ProposalId) -> []byte()`. + +## Vote Table + +The `voteTable` stores `Vote`s: `0x40 | []byte(ProposalId) | []byte(voter.Address) -> ProtocolBuffer(Vote)`. + +The `voteTable` is a primary key table and its `PrimaryKey` is given by +`[]byte(ProposalId) | []byte(voter.Address)` which is used by the following indexes. + +### voteByProposalIndex + +`voteByProposalIndex` allows to retrieve votes by proposal id: +`0x41 | []byte(ProposalId) | PrimaryKey | byte(len(PrimaryKey)) -> []byte()`. + +### voteByVoterIndex + +`voteByVoterIndex` allows to retrieve votes by voter address: +`0x42 | []byte(voter.Address) | PrimaryKey | byte(len(PrimaryKey)) -> []byte()`. + diff --git a/x/group/spec/03_messages.md b/x/group/spec/03_messages.md new file mode 100644 index 0000000000..329059c41c --- /dev/null +++ b/x/group/spec/03_messages.md @@ -0,0 +1,106 @@ + + +# Msg Service + +## Msg/CreateGroup + +A new group can be created with the `MsgCreateGroupRequest`, which has an admin address, a list of members and some optional metadata bytes. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L53-L64 + +It's expecting to fail if metadata length is greater than some `MaxMetadataLength`. + +## Msg/UpdateGroupMembers + +Group members can be updated with the `UpdateGroupMembersRequest`. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L73-L85 + +In the list of `MemberUpdates`, an existing member can be removed by setting its weight to 0. + +It's expecting to fail if the signer is not the admin of the group. + +## Msg/UpdateGroupAdmin + +The `UpdateGroupAdminRequest` can be used to update a group admin. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L90-L101 + +It's expecting to fail if the signer is not the admin of the group. + +## Msg/UpdateGroupMetadata + +The `UpdateGroupMetadataRequest` can be used to update a group metadata. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L106-L117 + +It's expecting to fail if: +- new metadata length is greater than some `MaxMetadataLength`. +- the signer is not the admin of the group. + +## Msg/CreateGroupAccount + +A new group account can be created with the `MsgCreateGroupAccountRequest`, which has an admin address, a group id, a decision policy and some optional metadata bytes. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L126-L141 + +It's expecting to fail if metadata length is greater than some `MaxMetadataLength`. + +## Msg/UpdateGroupAccountAdmin + +The `UpdateGroupAccountAdminRequest` can be used to update a group account admin. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L150-L161 + +It's expecting to fail if the signer is not the admin of the group account. + +## Msg/UpdateGroupAccountDecisionPolicy + +The `UpdateGroupAccountDecisionPolicyRequest` can be used to update a decision policy. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L166-L178 + +It's expecting to fail if the signer is not the admin of the group account. + +## Msg/UpdateGroupAccountMetadata + +The `UpdateGroupAccountMetadataRequest` can be used to update a group account metadata. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L183-L194 + +It's expecting to fail if: +- new metadata length is greater than some `MaxMetadataLength`. +- the signer is not the admin of the group. + +## Msg/CreateProposal + +A new group account can be created with the `MsgCreateProposalRequest`, which has a group account address, a list of proposers addresses, a list of messages to execute if the proposal is accepted and some optional metadata bytes. +An optional `Exec` value can be provided to try to execute the proposal immediately after proposal creation. Proposers signatures are considered as yes votes in this case. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L217-L238 + +It's expecting to fail if metadata length is greater than some `MaxMetadataLength`. + +## Msg/Vote + +A new vote can be created with the `MsgVoteRequest`, given a proposal id, a voter address, a choice (yes, no, veto or abstain) and some optional metadata bytes. +An optional `Exec` value can be provided to try to execute the proposal immediately after voting. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L247-L265 + +It's expecting to fail if metadata length is greater than some `MaxMetadataLength`. + +## Msg/Exec + +A proposal can be executed with the `MsgExecRequest`. + ++++ https://github.com/regen-network/regen-ledger/blob/8cebfb2d0dd000c42ae4d2da583629fdb96966c0/proto/regen/group/v1alpha1/tx.proto#L270-L278 + +The messages that are part of this proposal won't be executed if: +- the group has been modified before tally. +- the group account has been modified before tally. +- the proposal has not been accepted. +- the proposal status is not closed. +- the proposal has already been successfully executed. \ No newline at end of file diff --git a/x/group/spec/04_events.md b/x/group/spec/04_events.md new file mode 100644 index 0000000000..6f5f0b2108 --- /dev/null +++ b/x/group/spec/04_events.md @@ -0,0 +1,56 @@ + + +# Events + +The group module emits the following events: + +## EventCreateGroup + +| Type | Attribute Key | Attribute Value | +|---------------------------------------|---------------|---------------------------------------| +| message | action | /regen.group.v1alpha1.Msg/CreateGroup | +| regen.group.v1alpha1.EventCreateGroup | group_id | {groupId} | + +## EventUpdateGroup + +| Type | Attribute Key | Attribute Value | +|---------------------------------------|---------------|-----------------------------------------------------------------| +| message | action | /regen.group.v1alpha1.Msg/UpdateGroup{Admin\|Metadata\|Members} | +| regen.group.v1alpha1.EventUpdateGroup | group_id | {groupId} | + +## EventCreateGroupAccount + +| Type | Attribute Key | Attribute Value | +|----------------------------------------------|---------------|----------------------------------------------| +| message | action | /regen.group.v1alpha1.Msg/CreateGroupAccount | +| regen.group.v1alpha1.EventCreateGroupAccount | address | {groupAccountAddress} | + +## EventUpdateGroupAccount + +| Type | Attribute Key | Attribute Value | +|----------------------------------------------|---------------|-------------------------------------------------------------------------------| +| message | action | /regen.group.v1alpha1.Msg/UpdateGroupAccount{Admin\|Metadata\|DecisionPolicy} | +| regen.group.v1alpha1.EventUpdateGroupAccount | address | {groupAccountAddress} | + +## EventCreateProposal + +| Type | Attribute Key | Attribute Value | +|------------------------------------------|---------------|------------------------------------------| +| message | action | /regen.group.v1alpha1.Msg/CreateProposal | +| regen.group.v1alpha1.EventCreateProposal | proposal_id | {proposalId} | + +## EventVote + +| Type | Attribute Key | Attribute Value | +|--------------------------------|---------------|--------------------------------| +| message | action | /regen.group.v1alpha1.Msg/Vote | +| regen.group.v1alpha1.EventVote | proposal_id | {proposalId} | + +## EventExec + +| Type | Attribute Key | Attribute Value | +|--------------------------------|---------------|--------------------------------| +| message | action | /regen.group.v1alpha1.Msg/Exec | +| regen.group.v1alpha1.EventExec | proposal_id | {proposalId} | \ No newline at end of file diff --git a/x/group/spec/README.md b/x/group/spec/README.md new file mode 100644 index 0000000000..f821330ed5 --- /dev/null +++ b/x/group/spec/README.md @@ -0,0 +1,49 @@ + + +## Abstract + +This document specifies the group module. + +This module allows the creation and management of on-chain multisig accounts and enables voting for message execution based on configurable decision policies. + +## Contents + +1. **[Concepts](01_concepts.md)** + - [Group](01_concepts.md#group) + - [Group Account](01_concepts.md#group-account) + - [Decision Policy](01_concepts.md#decision-policy) + - [Proposal](01_concepts.md#proposal) + - [Voting](01_concepts.md#voting) + - [Executing Proposals](01_concepts.md#executing-proposals) +2. **[State](02_state.md)** + - [Group Table](02_state.md#group-table) + - [Group Member Table](02_state.md#group-member-table) + - [Group Account Table](02_state.md#group-account-table) + - [Proposal](02_state.md#proposal-table) + - [Vote Table](02_state.md#vote-table) +3. **[Msg Service](03_messages.md)** + - [Msg/CreateGroup](03_messages.md#msgcreategroup) + - [Msg/UpdateGroupMembers](03_messages.md#msgupdategroupmembers) + - [Msg/UpdateGroupAdmin](03_messages.md#msgupdategroupadmin) + - [Msg/UpdateGroupMetadata](03_messages.md#msgupdategroupmetadata) + - [Msg/CreateGroupAccount](03_messages.md#msgcreategroupaccount) + - [Msg/UpdateGroupAccountAdmin](03_messages.md#msgupdategroupaccountadmin) + - [Msg/UpdateGroupAccountDecisionPolicy](03_messages.md#msgupdategroupaccountdecisionpolicy) + - [Msg/UpdateGroupAccountMetadata](03_messages.md#msgupdategroupaccountmetadata) + - [Msg/CreateProposal](03_messages.md#msgcreateproposal) + - [Msg/Vote](03_messages.md#msgvote) + - [Msg/Exec](03_messages.md#msgexec) +4. **[Events](04_events.md)** + - [EventCreateGroup](04_events.md#eventcreategroup) + - [EventUpdateGroup](04_events.md#eventupdategroup) + - [EventCreateGroupAccount](04_events.md#eventcreategroupaccount) + - [EventUpdateGroupAccount](04_events.md#eventupdategroupaccount) + - [EventCreateProposal](04_events.md#eventcreateproposal) + - [EventVote](04_events.md#eventvote) + - [EventExec](04_events.md#eventexec) + diff --git a/x/group/testdata/tx.go b/x/group/testdata/tx.go new file mode 100644 index 0000000000..b894294c94 --- /dev/null +++ b/x/group/testdata/tx.go @@ -0,0 +1,29 @@ +package testdata + +import ( + "bytes" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/gogo/protobuf/jsonpb" +) + +var _ sdk.Msg = &MsgAuthenticated{} + +func (m MsgAuthenticated) Route() string { return "MsgAuthenticated" } + +func (m MsgAuthenticated) Type() string { return "Msg Authenticated" } + +// GetSignBytes returns the bytes for the message signer to sign on +func (m MsgAuthenticated) GetSignBytes() []byte { + var buf bytes.Buffer + enc := jsonpb.Marshaler{} + if err := enc.Marshal(&buf, &m); err != nil { + panic(err) + } + return sdk.MustSortJSON(buf.Bytes()) +} + +// ValidateBasic does a sanity check on the provided data +func (m MsgAuthenticated) ValidateBasic() error { + return nil +} diff --git a/x/group/testdata/tx.pb.go b/x/group/testdata/tx.pb.go new file mode 100644 index 0000000000..f41be475b9 --- /dev/null +++ b/x/group/testdata/tx.pb.go @@ -0,0 +1,327 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: tx.proto + +package testdata + +import ( + fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type MsgAuthenticated struct { + Signers []github_com_cosmos_cosmos_sdk_types.AccAddress `protobuf:"bytes,1,rep,name=signers,proto3,casttype=github.com/cosmos/cosmos-sdk/types.AccAddress" json:"signers,omitempty"` +} + +func (m *MsgAuthenticated) Reset() { *m = MsgAuthenticated{} } +func (m *MsgAuthenticated) String() string { return proto.CompactTextString(m) } +func (*MsgAuthenticated) ProtoMessage() {} +func (*MsgAuthenticated) Descriptor() ([]byte, []int) { + return fileDescriptor_0fd2153dc07d3b5c, []int{0} +} +func (m *MsgAuthenticated) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgAuthenticated) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgAuthenticated.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 *MsgAuthenticated) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgAuthenticated.Merge(m, src) +} +func (m *MsgAuthenticated) XXX_Size() int { + return m.Size() +} +func (m *MsgAuthenticated) XXX_DiscardUnknown() { + xxx_messageInfo_MsgAuthenticated.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgAuthenticated proto.InternalMessageInfo + +func (m *MsgAuthenticated) GetSigners() []github_com_cosmos_cosmos_sdk_types.AccAddress { + if m != nil { + return m.Signers + } + return nil +} + +func init() { + proto.RegisterType((*MsgAuthenticated)(nil), "testdata.MsgAuthenticated") +} + +func init() { proto.RegisterFile("tx.proto", fileDescriptor_0fd2153dc07d3b5c) } + +var fileDescriptor_0fd2153dc07d3b5c = []byte{ + // 212 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x28, 0xa9, 0xd0, 0x2b, + 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x28, 0x49, 0x2d, 0x2e, 0x49, 0x49, 0x2c, 0x49, 0x94, 0x12, + 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0x0b, 0xea, 0x83, 0x58, 0x10, 0x79, 0xa5, 0x78, 0x2e, 0x01, 0xdf, + 0xe2, 0x74, 0xc7, 0xd2, 0x92, 0x8c, 0xd4, 0xbc, 0x92, 0xcc, 0xe4, 0xc4, 0x92, 0xd4, 0x14, 0x21, + 0x6f, 0x2e, 0xf6, 0xe2, 0xcc, 0xf4, 0xbc, 0xd4, 0xa2, 0x62, 0x09, 0x46, 0x05, 0x66, 0x0d, 0x1e, + 0x27, 0xc3, 0x5f, 0xf7, 0xe4, 0x75, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, + 0xf5, 0x93, 0xf3, 0x8b, 0x73, 0xf3, 0x8b, 0xa1, 0x94, 0x6e, 0x71, 0x4a, 0xb6, 0x7e, 0x49, 0x65, + 0x41, 0x6a, 0xb1, 0x9e, 0x63, 0x72, 0xb2, 0x63, 0x4a, 0x4a, 0x51, 0x6a, 0x71, 0x71, 0x10, 0xcc, + 0x04, 0xa7, 0x80, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, + 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, 0x32, 0x43, 0x32, + 0xb1, 0x28, 0x35, 0x3d, 0x35, 0x4f, 0x37, 0x2f, 0xb5, 0xa4, 0x3c, 0xbf, 0x28, 0x1b, 0xca, 0xcb, + 0x49, 0x4d, 0x49, 0x4f, 0x2d, 0xd2, 0xaf, 0xd0, 0x4f, 0x2f, 0xca, 0x2f, 0x2d, 0xd0, 0x87, 0x79, + 0x24, 0x89, 0x0d, 0xec, 0x72, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x33, 0x5a, 0x15, 0x0a, + 0xe5, 0x00, 0x00, 0x00, +} + +func (m *MsgAuthenticated) 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 *MsgAuthenticated) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgAuthenticated) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signers) > 0 { + for iNdEx := len(m.Signers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Signers[iNdEx]) + copy(dAtA[i:], m.Signers[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signers[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgAuthenticated) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Signers) > 0 { + for _, b := range m.Signers { + l = len(b) + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgAuthenticated) 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: MsgAuthenticated: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgAuthenticated: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signers", 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.Signers = append(m.Signers, make([]byte, postIndex-iNdEx)) + copy(m.Signers[len(m.Signers)-1], dAtA[iNdEx:postIndex]) + 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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/group/testdata/tx.proto b/x/group/testdata/tx.proto new file mode 100644 index 0000000000..ca10364ef3 --- /dev/null +++ b/x/group/testdata/tx.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; + +package testdata; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/cosmos/cosmos-sdk/x/group/testdata"; + +message MsgAuthenticated { + repeated bytes signers = 1 [(gogoproto.casttype) = "github.com/cosmos/cosmos-sdk/types.AccAddress"]; +} diff --git a/x/group/tx.pb.go b/x/group/tx.pb.go new file mode 100644 index 0000000000..47a1f58f50 --- /dev/null +++ b/x/group/tx.pb.go @@ -0,0 +1,9002 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: regen/group/v1alpha1/tx.proto + +package group + +import ( + 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" + types1 "github.com/gogo/protobuf/types" + _ "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" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Exec defines modes of execution of a proposal on creation or on new vote. +type Exec int32 + +const ( + // An empty value means that there should be a separate + // MsgExec request for the proposal to execute. + Exec_EXEC_UNSPECIFIED Exec = 0 + // Try to execute the proposal immediately. + // If the proposal is not allowed per the DecisionPolicy, + // the proposal will still be open and could + // be executed at a later point. + Exec_EXEC_TRY Exec = 1 +) + +var Exec_name = map[int32]string{ + 0: "EXEC_UNSPECIFIED", + 1: "EXEC_TRY", +} + +var Exec_value = map[string]int32{ + "EXEC_UNSPECIFIED": 0, + "EXEC_TRY": 1, +} + +func (x Exec) String() string { + return proto.EnumName(Exec_name, int32(x)) +} + +func (Exec) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{0} +} + +// MsgCreateGroup is the Msg/CreateGroup request type. +type MsgCreateGroup struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // members defines the group members. + Members []Member `protobuf:"bytes,2,rep,name=members,proto3" json:"members"` + // metadata is any arbitrary metadata to attached to the group. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` + // bls_only requires all the group members to use bls public keys so their votes can be aggregated together + BlsOnly bool `protobuf:"varint,4,opt,name=bls_only,json=blsOnly,proto3" json:"bls_only,omitempty"` +} + +func (m *MsgCreateGroup) Reset() { *m = MsgCreateGroup{} } +func (m *MsgCreateGroup) String() string { return proto.CompactTextString(m) } +func (*MsgCreateGroup) ProtoMessage() {} +func (*MsgCreateGroup) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{0} +} +func (m *MsgCreateGroup) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateGroup.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 *MsgCreateGroup) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateGroup.Merge(m, src) +} +func (m *MsgCreateGroup) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateGroup) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateGroup.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateGroup proto.InternalMessageInfo + +func (m *MsgCreateGroup) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgCreateGroup) GetMembers() []Member { + if m != nil { + return m.Members + } + return nil +} + +func (m *MsgCreateGroup) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *MsgCreateGroup) GetBlsOnly() bool { + if m != nil { + return m.BlsOnly + } + return false +} + +// MsgCreateGroupResponse is the Msg/CreateGroup response type. +type MsgCreateGroupResponse struct { + // group_id is the unique ID of the newly created group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` +} + +func (m *MsgCreateGroupResponse) Reset() { *m = MsgCreateGroupResponse{} } +func (m *MsgCreateGroupResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateGroupResponse) ProtoMessage() {} +func (*MsgCreateGroupResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{1} +} +func (m *MsgCreateGroupResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateGroupResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateGroupResponse.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 *MsgCreateGroupResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateGroupResponse.Merge(m, src) +} +func (m *MsgCreateGroupResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateGroupResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateGroupResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateGroupResponse proto.InternalMessageInfo + +func (m *MsgCreateGroupResponse) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +// MsgUpdateGroupMembers is the Msg/UpdateGroupMembers request type. +type MsgUpdateGroupMembers struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // member_updates is the list of members to update, + // set weight to 0 to remove a member. + MemberUpdates []Member `protobuf:"bytes,3,rep,name=member_updates,json=memberUpdates,proto3" json:"member_updates"` +} + +func (m *MsgUpdateGroupMembers) Reset() { *m = MsgUpdateGroupMembers{} } +func (m *MsgUpdateGroupMembers) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupMembers) ProtoMessage() {} +func (*MsgUpdateGroupMembers) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{2} +} +func (m *MsgUpdateGroupMembers) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupMembers) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupMembers.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 *MsgUpdateGroupMembers) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupMembers.Merge(m, src) +} +func (m *MsgUpdateGroupMembers) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupMembers) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupMembers.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupMembers proto.InternalMessageInfo + +func (m *MsgUpdateGroupMembers) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgUpdateGroupMembers) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *MsgUpdateGroupMembers) GetMemberUpdates() []Member { + if m != nil { + return m.MemberUpdates + } + return nil +} + +// MsgUpdateGroupMembersResponse is the Msg/UpdateGroupMembers response type. +type MsgUpdateGroupMembersResponse struct { +} + +func (m *MsgUpdateGroupMembersResponse) Reset() { *m = MsgUpdateGroupMembersResponse{} } +func (m *MsgUpdateGroupMembersResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupMembersResponse) ProtoMessage() {} +func (*MsgUpdateGroupMembersResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{3} +} +func (m *MsgUpdateGroupMembersResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupMembersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupMembersResponse.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 *MsgUpdateGroupMembersResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupMembersResponse.Merge(m, src) +} +func (m *MsgUpdateGroupMembersResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupMembersResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupMembersResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupMembersResponse proto.InternalMessageInfo + +// MsgUpdateGroupAdmin is the Msg/UpdateGroupAdmin request type. +type MsgUpdateGroupAdmin struct { + // admin is the current account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // new_admin is the group new admin account address. + NewAdmin string `protobuf:"bytes,3,opt,name=new_admin,json=newAdmin,proto3" json:"new_admin,omitempty"` +} + +func (m *MsgUpdateGroupAdmin) Reset() { *m = MsgUpdateGroupAdmin{} } +func (m *MsgUpdateGroupAdmin) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAdmin) ProtoMessage() {} +func (*MsgUpdateGroupAdmin) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{4} +} +func (m *MsgUpdateGroupAdmin) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAdmin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAdmin.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 *MsgUpdateGroupAdmin) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAdmin.Merge(m, src) +} +func (m *MsgUpdateGroupAdmin) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAdmin) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAdmin.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAdmin proto.InternalMessageInfo + +func (m *MsgUpdateGroupAdmin) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgUpdateGroupAdmin) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *MsgUpdateGroupAdmin) GetNewAdmin() string { + if m != nil { + return m.NewAdmin + } + return "" +} + +// MsgUpdateGroupAdminResponse is the Msg/UpdateGroupAdmin response type. +type MsgUpdateGroupAdminResponse struct { +} + +func (m *MsgUpdateGroupAdminResponse) Reset() { *m = MsgUpdateGroupAdminResponse{} } +func (m *MsgUpdateGroupAdminResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAdminResponse) ProtoMessage() {} +func (*MsgUpdateGroupAdminResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{5} +} +func (m *MsgUpdateGroupAdminResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAdminResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAdminResponse.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 *MsgUpdateGroupAdminResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAdminResponse.Merge(m, src) +} +func (m *MsgUpdateGroupAdminResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAdminResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAdminResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAdminResponse proto.InternalMessageInfo + +// MsgUpdateGroupMetadata is the Msg/UpdateGroupMetadata request type. +type MsgUpdateGroupMetadata struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // metadata is the updated group's metadata. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (m *MsgUpdateGroupMetadata) Reset() { *m = MsgUpdateGroupMetadata{} } +func (m *MsgUpdateGroupMetadata) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupMetadata) ProtoMessage() {} +func (*MsgUpdateGroupMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{6} +} +func (m *MsgUpdateGroupMetadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupMetadata.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 *MsgUpdateGroupMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupMetadata.Merge(m, src) +} +func (m *MsgUpdateGroupMetadata) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupMetadata proto.InternalMessageInfo + +func (m *MsgUpdateGroupMetadata) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgUpdateGroupMetadata) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *MsgUpdateGroupMetadata) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +// MsgUpdateGroupMetadataResponse is the Msg/UpdateGroupMetadata response type. +type MsgUpdateGroupMetadataResponse struct { +} + +func (m *MsgUpdateGroupMetadataResponse) Reset() { *m = MsgUpdateGroupMetadataResponse{} } +func (m *MsgUpdateGroupMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupMetadataResponse) ProtoMessage() {} +func (*MsgUpdateGroupMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{7} +} +func (m *MsgUpdateGroupMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupMetadataResponse.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 *MsgUpdateGroupMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupMetadataResponse.Merge(m, src) +} +func (m *MsgUpdateGroupMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupMetadataResponse proto.InternalMessageInfo + +// MsgCreateGroupAccount is the Msg/CreateGroupAccount request type. +type MsgCreateGroupAccount struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // metadata is any arbitrary metadata to attached to the group account. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` + // decision_policy specifies the group account's decision policy. + DecisionPolicy *types.Any `protobuf:"bytes,4,opt,name=decision_policy,json=decisionPolicy,proto3" json:"decision_policy,omitempty"` +} + +func (m *MsgCreateGroupAccount) Reset() { *m = MsgCreateGroupAccount{} } +func (m *MsgCreateGroupAccount) String() string { return proto.CompactTextString(m) } +func (*MsgCreateGroupAccount) ProtoMessage() {} +func (*MsgCreateGroupAccount) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{8} +} +func (m *MsgCreateGroupAccount) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateGroupAccount) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateGroupAccount.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 *MsgCreateGroupAccount) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateGroupAccount.Merge(m, src) +} +func (m *MsgCreateGroupAccount) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateGroupAccount) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateGroupAccount.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateGroupAccount proto.InternalMessageInfo + +// MsgCreateGroupAccountResponse is the Msg/CreateGroupAccount response type. +type MsgCreateGroupAccountResponse struct { + // address is the account address of the newly created group account. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *MsgCreateGroupAccountResponse) Reset() { *m = MsgCreateGroupAccountResponse{} } +func (m *MsgCreateGroupAccountResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateGroupAccountResponse) ProtoMessage() {} +func (*MsgCreateGroupAccountResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{9} +} +func (m *MsgCreateGroupAccountResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateGroupAccountResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateGroupAccountResponse.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 *MsgCreateGroupAccountResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateGroupAccountResponse.Merge(m, src) +} +func (m *MsgCreateGroupAccountResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateGroupAccountResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateGroupAccountResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateGroupAccountResponse proto.InternalMessageInfo + +func (m *MsgCreateGroupAccountResponse) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +// MsgUpdateGroupAccountAdmin is the Msg/UpdateGroupAccountAdmin request type. +type MsgUpdateGroupAccountAdmin struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // address is the group account address. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // new_admin is the new group account admin. + NewAdmin string `protobuf:"bytes,3,opt,name=new_admin,json=newAdmin,proto3" json:"new_admin,omitempty"` +} + +func (m *MsgUpdateGroupAccountAdmin) Reset() { *m = MsgUpdateGroupAccountAdmin{} } +func (m *MsgUpdateGroupAccountAdmin) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAccountAdmin) ProtoMessage() {} +func (*MsgUpdateGroupAccountAdmin) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{10} +} +func (m *MsgUpdateGroupAccountAdmin) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAccountAdmin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAccountAdmin.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 *MsgUpdateGroupAccountAdmin) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAccountAdmin.Merge(m, src) +} +func (m *MsgUpdateGroupAccountAdmin) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAccountAdmin) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAccountAdmin.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAccountAdmin proto.InternalMessageInfo + +func (m *MsgUpdateGroupAccountAdmin) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgUpdateGroupAccountAdmin) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgUpdateGroupAccountAdmin) GetNewAdmin() string { + if m != nil { + return m.NewAdmin + } + return "" +} + +// MsgUpdateGroupAccountAdminResponse is the Msg/UpdateGroupAccountAdmin response type. +type MsgUpdateGroupAccountAdminResponse struct { +} + +func (m *MsgUpdateGroupAccountAdminResponse) Reset() { *m = MsgUpdateGroupAccountAdminResponse{} } +func (m *MsgUpdateGroupAccountAdminResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAccountAdminResponse) ProtoMessage() {} +func (*MsgUpdateGroupAccountAdminResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{11} +} +func (m *MsgUpdateGroupAccountAdminResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAccountAdminResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAccountAdminResponse.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 *MsgUpdateGroupAccountAdminResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAccountAdminResponse.Merge(m, src) +} +func (m *MsgUpdateGroupAccountAdminResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAccountAdminResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAccountAdminResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAccountAdminResponse proto.InternalMessageInfo + +// MsgUpdateGroupAccountDecisionPolicy is the Msg/UpdateGroupAccountDecisionPolicy request type. +type MsgUpdateGroupAccountDecisionPolicy struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // address is the group account address. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // decision_policy is the updated group account decision policy. + DecisionPolicy *types.Any `protobuf:"bytes,3,opt,name=decision_policy,json=decisionPolicy,proto3" json:"decision_policy,omitempty"` +} + +func (m *MsgUpdateGroupAccountDecisionPolicy) Reset() { *m = MsgUpdateGroupAccountDecisionPolicy{} } +func (m *MsgUpdateGroupAccountDecisionPolicy) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAccountDecisionPolicy) ProtoMessage() {} +func (*MsgUpdateGroupAccountDecisionPolicy) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{12} +} +func (m *MsgUpdateGroupAccountDecisionPolicy) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAccountDecisionPolicy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicy.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 *MsgUpdateGroupAccountDecisionPolicy) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicy.Merge(m, src) +} +func (m *MsgUpdateGroupAccountDecisionPolicy) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAccountDecisionPolicy) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicy.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicy proto.InternalMessageInfo + +// MsgUpdateGroupAccountDecisionPolicyResponse is the Msg/UpdateGroupAccountDecisionPolicy response type. +type MsgUpdateGroupAccountDecisionPolicyResponse struct { +} + +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) Reset() { + *m = MsgUpdateGroupAccountDecisionPolicyResponse{} +} +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) String() string { + return proto.CompactTextString(m) +} +func (*MsgUpdateGroupAccountDecisionPolicyResponse) ProtoMessage() {} +func (*MsgUpdateGroupAccountDecisionPolicyResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{13} +} +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicyResponse.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 *MsgUpdateGroupAccountDecisionPolicyResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicyResponse.Merge(m, src) +} +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicyResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAccountDecisionPolicyResponse proto.InternalMessageInfo + +// MsgUpdateGroupAccountMetadata is the Msg/UpdateGroupAccountMetadata request type. +type MsgUpdateGroupAccountMetadata struct { + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,1,opt,name=admin,proto3" json:"admin,omitempty"` + // address is the group account address. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // metadata is the updated group account metadata. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (m *MsgUpdateGroupAccountMetadata) Reset() { *m = MsgUpdateGroupAccountMetadata{} } +func (m *MsgUpdateGroupAccountMetadata) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAccountMetadata) ProtoMessage() {} +func (*MsgUpdateGroupAccountMetadata) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{14} +} +func (m *MsgUpdateGroupAccountMetadata) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAccountMetadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAccountMetadata.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 *MsgUpdateGroupAccountMetadata) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAccountMetadata.Merge(m, src) +} +func (m *MsgUpdateGroupAccountMetadata) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAccountMetadata) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAccountMetadata.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAccountMetadata proto.InternalMessageInfo + +func (m *MsgUpdateGroupAccountMetadata) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *MsgUpdateGroupAccountMetadata) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *MsgUpdateGroupAccountMetadata) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +// MsgUpdateGroupAccountMetadataResponse is the Msg/UpdateGroupAccountMetadata response type. +type MsgUpdateGroupAccountMetadataResponse struct { +} + +func (m *MsgUpdateGroupAccountMetadataResponse) Reset() { *m = MsgUpdateGroupAccountMetadataResponse{} } +func (m *MsgUpdateGroupAccountMetadataResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateGroupAccountMetadataResponse) ProtoMessage() {} +func (*MsgUpdateGroupAccountMetadataResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{15} +} +func (m *MsgUpdateGroupAccountMetadataResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateGroupAccountMetadataResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateGroupAccountMetadataResponse.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 *MsgUpdateGroupAccountMetadataResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateGroupAccountMetadataResponse.Merge(m, src) +} +func (m *MsgUpdateGroupAccountMetadataResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateGroupAccountMetadataResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateGroupAccountMetadataResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateGroupAccountMetadataResponse proto.InternalMessageInfo + +// MsgCreateProposal is the Msg/CreateProposal request type. +type MsgCreateProposal struct { + // address is the group account address. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // proposers are the account addresses of the proposers. + // Proposers signatures will be counted as yes votes. + Proposers []string `protobuf:"bytes,2,rep,name=proposers,proto3" json:"proposers,omitempty"` + // metadata is any arbitrary metadata to attached to the proposal. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` + // msgs is a list of Msgs that will be executed if the proposal passes. + Msgs []*types.Any `protobuf:"bytes,4,rep,name=msgs,proto3" json:"msgs,omitempty"` + // exec defines the mode of execution of the proposal, + // whether it should be executed immediately on creation or not. + // If so, proposers signatures are considered as Yes votes. + Exec Exec `protobuf:"varint,5,opt,name=exec,proto3,enum=regen.group.v1alpha1.Exec" json:"exec,omitempty"` +} + +func (m *MsgCreateProposal) Reset() { *m = MsgCreateProposal{} } +func (m *MsgCreateProposal) String() string { return proto.CompactTextString(m) } +func (*MsgCreateProposal) ProtoMessage() {} +func (*MsgCreateProposal) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{16} +} +func (m *MsgCreateProposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateProposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateProposal.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 *MsgCreateProposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateProposal.Merge(m, src) +} +func (m *MsgCreateProposal) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateProposal) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateProposal.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateProposal proto.InternalMessageInfo + +// MsgCreateProposalResponse is the Msg/CreateProposal response type. +type MsgCreateProposalResponse struct { + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` +} + +func (m *MsgCreateProposalResponse) Reset() { *m = MsgCreateProposalResponse{} } +func (m *MsgCreateProposalResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateProposalResponse) ProtoMessage() {} +func (*MsgCreateProposalResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{17} +} +func (m *MsgCreateProposalResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateProposalResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateProposalResponse.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 *MsgCreateProposalResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateProposalResponse.Merge(m, src) +} +func (m *MsgCreateProposalResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateProposalResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateProposalResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateProposalResponse proto.InternalMessageInfo + +func (m *MsgCreateProposalResponse) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +// MsgVote is the Msg/Vote request type. +type MsgVote struct { + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // voter is the voter account address. + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + // choice is the voter's choice on the proposal. + Choice Choice `protobuf:"varint,3,opt,name=choice,proto3,enum=regen.group.v1alpha1.Choice" json:"choice,omitempty"` + // metadata is any arbitrary metadata to attached to the vote. + Metadata []byte `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // exec defines whether the proposal should be executed + // immediately after voting or not. + Exec Exec `protobuf:"varint,5,opt,name=exec,proto3,enum=regen.group.v1alpha1.Exec" json:"exec,omitempty"` +} + +func (m *MsgVote) Reset() { *m = MsgVote{} } +func (m *MsgVote) String() string { return proto.CompactTextString(m) } +func (*MsgVote) ProtoMessage() {} +func (*MsgVote) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{18} +} +func (m *MsgVote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVote.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 *MsgVote) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVote.Merge(m, src) +} +func (m *MsgVote) XXX_Size() int { + return m.Size() +} +func (m *MsgVote) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVote.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVote proto.InternalMessageInfo + +func (m *MsgVote) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *MsgVote) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *MsgVote) GetChoice() Choice { + if m != nil { + return m.Choice + } + return Choice_CHOICE_UNSPECIFIED +} + +func (m *MsgVote) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *MsgVote) GetExec() Exec { + if m != nil { + return m.Exec + } + return Exec_EXEC_UNSPECIFIED +} + +// MsgVoteResponse is the Msg/Vote response type. +type MsgVoteResponse struct { +} + +func (m *MsgVoteResponse) Reset() { *m = MsgVoteResponse{} } +func (m *MsgVoteResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVoteResponse) ProtoMessage() {} +func (*MsgVoteResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{19} +} +func (m *MsgVoteResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteResponse.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 *MsgVoteResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteResponse.Merge(m, src) +} +func (m *MsgVoteResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteResponse proto.InternalMessageInfo + +// MsgVoteBasicRequest is the Msg/Vote request type. +type MsgVoteBasic struct { + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // choice is the voter's choice on the proposal. + Choice Choice `protobuf:"varint,2,opt,name=choice,proto3,enum=regen.group.v1alpha1.Choice" json:"choice,omitempty"` + // expiry is the timestamp after which the basic vote expires. + Expiry types1.Timestamp `protobuf:"bytes,3,opt,name=expiry,proto3" json:"expiry"` +} + +func (m *MsgVoteBasic) Reset() { *m = MsgVoteBasic{} } +func (m *MsgVoteBasic) String() string { return proto.CompactTextString(m) } +func (*MsgVoteBasic) ProtoMessage() {} +func (*MsgVoteBasic) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{20} +} +func (m *MsgVoteBasic) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteBasic) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteBasic.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 *MsgVoteBasic) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteBasic.Merge(m, src) +} +func (m *MsgVoteBasic) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteBasic) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteBasic.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteBasic proto.InternalMessageInfo + +func (m *MsgVoteBasic) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *MsgVoteBasic) GetChoice() Choice { + if m != nil { + return m.Choice + } + return Choice_CHOICE_UNSPECIFIED +} + +func (m *MsgVoteBasic) GetExpiry() types1.Timestamp { + if m != nil { + return m.Expiry + } + return types1.Timestamp{} +} + +// MsgVoteResponse is the basic vote that can be aggregated together +type MsgVoteBasicResponse struct { + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // choice is the voter's choice on the proposal. + Choice Choice `protobuf:"varint,2,opt,name=choice,proto3,enum=regen.group.v1alpha1.Choice" json:"choice,omitempty"` + // expiry is the timestamp after which the basic vote expires. + Expiry types1.Timestamp `protobuf:"bytes,3,opt,name=expiry,proto3" json:"expiry"` + // voter is the account address of the voter. + Voter string `protobuf:"bytes,4,opt,name=voter,proto3" json:"voter,omitempty"` + // pub_key is the voter's public key + PubKey *types.Any `protobuf:"bytes,5,opt,name=pub_key,json=pubKey,proto3" json:"public_key,omitempty" yaml:"public_key"` + // sig is the individual signature which will be aggregated with other signatures + Sig []byte `protobuf:"bytes,6,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (m *MsgVoteBasicResponse) Reset() { *m = MsgVoteBasicResponse{} } +func (m *MsgVoteBasicResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVoteBasicResponse) ProtoMessage() {} +func (*MsgVoteBasicResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{21} +} +func (m *MsgVoteBasicResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteBasicResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteBasicResponse.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 *MsgVoteBasicResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteBasicResponse.Merge(m, src) +} +func (m *MsgVoteBasicResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteBasicResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteBasicResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteBasicResponse proto.InternalMessageInfo + +func (m *MsgVoteBasicResponse) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *MsgVoteBasicResponse) GetChoice() Choice { + if m != nil { + return m.Choice + } + return Choice_CHOICE_UNSPECIFIED +} + +func (m *MsgVoteBasicResponse) GetExpiry() types1.Timestamp { + if m != nil { + return m.Expiry + } + return types1.Timestamp{} +} + +func (m *MsgVoteBasicResponse) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *MsgVoteBasicResponse) GetPubKey() *types.Any { + if m != nil { + return m.PubKey + } + return nil +} + +func (m *MsgVoteBasicResponse) GetSig() []byte { + if m != nil { + return m.Sig + } + return nil +} + +// MsgVoteAgg is the Msg/VoteAgg request type. +type MsgVoteAgg struct { + // sender is the person who submits the votes + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,2,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // votes are the list of voters' choices on the proposal. + Votes []Choice `protobuf:"varint,3,rep,packed,name=votes,proto3,enum=regen.group.v1alpha1.Choice" json:"votes,omitempty"` + // expiry is the timestamp after which the basic vote expires. + // All the basic votes to be aggregated must have the same expiry. + // Expiry should be set to be before the proposal timeout in order to + // prevent replay attacks and also prevent the aggregator from removing + // some basic votes. + Expiry types1.Timestamp `protobuf:"bytes,4,opt,name=expiry,proto3" json:"expiry"` + // agg_sig is the bls aggregated signature for all the votes + AggSig []byte `protobuf:"bytes,5,opt,name=agg_sig,json=aggSig,proto3" json:"agg_sig,omitempty"` + // metadata is any arbitrary metadata to attached to the vote. + Metadata []byte `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"` + // exec defines whether the proposal should be executed + // immediately after voting or not. + Exec Exec `protobuf:"varint,7,opt,name=exec,proto3,enum=regen.group.v1alpha1.Exec" json:"exec,omitempty"` +} + +func (m *MsgVoteAgg) Reset() { *m = MsgVoteAgg{} } +func (m *MsgVoteAgg) String() string { return proto.CompactTextString(m) } +func (*MsgVoteAgg) ProtoMessage() {} +func (*MsgVoteAgg) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{22} +} +func (m *MsgVoteAgg) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteAgg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteAgg.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 *MsgVoteAgg) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteAgg.Merge(m, src) +} +func (m *MsgVoteAgg) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteAgg) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteAgg.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteAgg proto.InternalMessageInfo + +func (m *MsgVoteAgg) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgVoteAgg) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *MsgVoteAgg) GetVotes() []Choice { + if m != nil { + return m.Votes + } + return nil +} + +func (m *MsgVoteAgg) GetExpiry() types1.Timestamp { + if m != nil { + return m.Expiry + } + return types1.Timestamp{} +} + +func (m *MsgVoteAgg) GetAggSig() []byte { + if m != nil { + return m.AggSig + } + return nil +} + +func (m *MsgVoteAgg) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *MsgVoteAgg) GetExec() Exec { + if m != nil { + return m.Exec + } + return Exec_EXEC_UNSPECIFIED +} + +// MsgVoteResponse is the Msg/Vote response type. +type MsgVoteAggResponse struct { +} + +func (m *MsgVoteAggResponse) Reset() { *m = MsgVoteAggResponse{} } +func (m *MsgVoteAggResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVoteAggResponse) ProtoMessage() {} +func (*MsgVoteAggResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{23} +} +func (m *MsgVoteAggResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVoteAggResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVoteAggResponse.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 *MsgVoteAggResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVoteAggResponse.Merge(m, src) +} +func (m *MsgVoteAggResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVoteAggResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVoteAggResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVoteAggResponse proto.InternalMessageInfo + +// MsgExec is the Msg/Exec request type. +type MsgExec struct { + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // signer is the account address used to execute the proposal. + Signer string `protobuf:"bytes,2,opt,name=signer,proto3" json:"signer,omitempty"` +} + +func (m *MsgExec) Reset() { *m = MsgExec{} } +func (m *MsgExec) String() string { return proto.CompactTextString(m) } +func (*MsgExec) ProtoMessage() {} +func (*MsgExec) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{24} +} +func (m *MsgExec) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgExec) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgExec.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 *MsgExec) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgExec.Merge(m, src) +} +func (m *MsgExec) XXX_Size() int { + return m.Size() +} +func (m *MsgExec) XXX_DiscardUnknown() { + xxx_messageInfo_MsgExec.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgExec proto.InternalMessageInfo + +func (m *MsgExec) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *MsgExec) GetSigner() string { + if m != nil { + return m.Signer + } + return "" +} + +// MsgExecResponse is the Msg/Exec request type. +type MsgExecResponse struct { +} + +func (m *MsgExecResponse) Reset() { *m = MsgExecResponse{} } +func (m *MsgExecResponse) String() string { return proto.CompactTextString(m) } +func (*MsgExecResponse) ProtoMessage() {} +func (*MsgExecResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{25} +} +func (m *MsgExecResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgExecResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgExecResponse.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 *MsgExecResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgExecResponse.Merge(m, src) +} +func (m *MsgExecResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgExecResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgExecResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgExecResponse proto.InternalMessageInfo + +// MsgCreateProposal is the Msg/CreateProposal request type. +type MsgCreatePoll struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + Options Options `protobuf:"bytes,3,opt,name=options,proto3" json:"options"` + Creator string `protobuf:"bytes,4,opt,name=creator,proto3" json:"creator,omitempty"` + // vote_limit is the number of options each voter can choose. + VoteLimit int32 `protobuf:"varint,5,opt,name=vote_limit,json=voteLimit,proto3" json:"vote_limit,omitempty"` + // metadata is any arbitrary metadata to attached to the proposal. + Metadata []byte `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"` + // timeout is the deadline of the poll. + Timeout types1.Timestamp `protobuf:"bytes,7,opt,name=timeout,proto3" json:"timeout"` +} + +func (m *MsgCreatePoll) Reset() { *m = MsgCreatePoll{} } +func (m *MsgCreatePoll) String() string { return proto.CompactTextString(m) } +func (*MsgCreatePoll) ProtoMessage() {} +func (*MsgCreatePoll) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{26} +} +func (m *MsgCreatePoll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreatePoll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreatePoll.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 *MsgCreatePoll) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreatePoll.Merge(m, src) +} +func (m *MsgCreatePoll) XXX_Size() int { + return m.Size() +} +func (m *MsgCreatePoll) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreatePoll.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreatePoll proto.InternalMessageInfo + +// MsgCreateProposalResponse is the Msg/CreateProposal response type. +type MsgCreatePollResponse struct { + // poll_id is the unique ID of the poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` +} + +func (m *MsgCreatePollResponse) Reset() { *m = MsgCreatePollResponse{} } +func (m *MsgCreatePollResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreatePollResponse) ProtoMessage() {} +func (*MsgCreatePollResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{27} +} +func (m *MsgCreatePollResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreatePollResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreatePollResponse.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 *MsgCreatePollResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreatePollResponse.Merge(m, src) +} +func (m *MsgCreatePollResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreatePollResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreatePollResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreatePollResponse proto.InternalMessageInfo + +func (m *MsgCreatePollResponse) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +// MsgVotePoll is the Msg/VotePoll request type. +type MsgVotePoll struct { + // poll_id is the unique ID of the poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // voter is the voter account address. + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + // options are the voter's choices on the poll. + Options Options `protobuf:"bytes,3,opt,name=options,proto3" json:"options"` + // metadata is any arbitrary metadata to attached to the vote. + Metadata []byte `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (m *MsgVotePoll) Reset() { *m = MsgVotePoll{} } +func (m *MsgVotePoll) String() string { return proto.CompactTextString(m) } +func (*MsgVotePoll) ProtoMessage() {} +func (*MsgVotePoll) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{28} +} +func (m *MsgVotePoll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVotePoll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVotePoll.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 *MsgVotePoll) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVotePoll.Merge(m, src) +} +func (m *MsgVotePoll) XXX_Size() int { + return m.Size() +} +func (m *MsgVotePoll) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVotePoll.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVotePoll proto.InternalMessageInfo + +func (m *MsgVotePoll) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *MsgVotePoll) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *MsgVotePoll) GetOptions() Options { + if m != nil { + return m.Options + } + return Options{} +} + +func (m *MsgVotePoll) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +// MsgVotePollResponse is the Msg/VotePoll response type. +type MsgVotePollResponse struct { +} + +func (m *MsgVotePollResponse) Reset() { *m = MsgVotePollResponse{} } +func (m *MsgVotePollResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVotePollResponse) ProtoMessage() {} +func (*MsgVotePollResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{29} +} +func (m *MsgVotePollResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVotePollResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVotePollResponse.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 *MsgVotePollResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVotePollResponse.Merge(m, src) +} +func (m *MsgVotePollResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVotePollResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVotePollResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVotePollResponse proto.InternalMessageInfo + +// MsgVoteBasicRequest is the Msg/Vote request type. +type MsgVotePollBasic struct { + // poll_id is the unique ID of the poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // option is one of the voter's choices on the poll. + Option string `protobuf:"bytes,2,opt,name=option,proto3" json:"option,omitempty"` + // expiry is the unique timestamp after which the basic vote expires. + Expiry types1.Timestamp `protobuf:"bytes,3,opt,name=expiry,proto3" json:"expiry"` +} + +func (m *MsgVotePollBasic) Reset() { *m = MsgVotePollBasic{} } +func (m *MsgVotePollBasic) String() string { return proto.CompactTextString(m) } +func (*MsgVotePollBasic) ProtoMessage() {} +func (*MsgVotePollBasic) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{30} +} +func (m *MsgVotePollBasic) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVotePollBasic) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVotePollBasic.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 *MsgVotePollBasic) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVotePollBasic.Merge(m, src) +} +func (m *MsgVotePollBasic) XXX_Size() int { + return m.Size() +} +func (m *MsgVotePollBasic) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVotePollBasic.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVotePollBasic proto.InternalMessageInfo + +func (m *MsgVotePollBasic) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *MsgVotePollBasic) GetOption() string { + if m != nil { + return m.Option + } + return "" +} + +func (m *MsgVotePollBasic) GetExpiry() types1.Timestamp { + if m != nil { + return m.Expiry + } + return types1.Timestamp{} +} + +// MsgVoteResponse is the basic vote that can be aggregated together +type MsgVotePollBasicResponse struct { + // proposal is the unique ID of the proposal. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // options are the voter's choices on the poll. + Options Options `protobuf:"bytes,2,opt,name=options,proto3" json:"options"` + // expiry is the timestamp after which the basic vote expires. + Expiry types1.Timestamp `protobuf:"bytes,3,opt,name=expiry,proto3" json:"expiry"` + // voter is the account address of the voter. + Voter string `protobuf:"bytes,4,opt,name=voter,proto3" json:"voter,omitempty"` + // pub_key is the voter's public key + PubKey *types.Any `protobuf:"bytes,5,opt,name=pub_key,json=pubKey,proto3" json:"public_key,omitempty" yaml:"public_key"` + // sig is the individual signature which will be aggregated with other voters' signatures + Sig []byte `protobuf:"bytes,6,opt,name=sig,proto3" json:"sig,omitempty"` +} + +func (m *MsgVotePollBasicResponse) Reset() { *m = MsgVotePollBasicResponse{} } +func (m *MsgVotePollBasicResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVotePollBasicResponse) ProtoMessage() {} +func (*MsgVotePollBasicResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{31} +} +func (m *MsgVotePollBasicResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVotePollBasicResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVotePollBasicResponse.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 *MsgVotePollBasicResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVotePollBasicResponse.Merge(m, src) +} +func (m *MsgVotePollBasicResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVotePollBasicResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVotePollBasicResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVotePollBasicResponse proto.InternalMessageInfo + +func (m *MsgVotePollBasicResponse) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *MsgVotePollBasicResponse) GetOptions() Options { + if m != nil { + return m.Options + } + return Options{} +} + +func (m *MsgVotePollBasicResponse) GetExpiry() types1.Timestamp { + if m != nil { + return m.Expiry + } + return types1.Timestamp{} +} + +func (m *MsgVotePollBasicResponse) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *MsgVotePollBasicResponse) GetPubKey() *types.Any { + if m != nil { + return m.PubKey + } + return nil +} + +func (m *MsgVotePollBasicResponse) GetSig() []byte { + if m != nil { + return m.Sig + } + return nil +} + +// MsgVoteAgg is the Msg/VoteAgg request type. +type MsgVotePollAgg struct { + // sender is the person who submits the votes + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty"` + // poll_id is the unique ID of the poll. + PollId uint64 `protobuf:"varint,2,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // votes are the full list of voters' choices on the proposal. + Votes []Options `protobuf:"bytes,3,rep,name=votes,proto3" json:"votes"` + // expiry is the timestamp after which the basic vote expires. + // All the basic votes to be aggregated must have the same expiry. + // Expiry should be set to be before the poll timeout in order to + // prevent replay attacks and also prevent the aggregator from removing + // some basic votes. + Expiry types1.Timestamp `protobuf:"bytes,4,opt,name=expiry,proto3" json:"expiry"` + // agg_sig is the bls aggregated signature for all the votes + AggSig []byte `protobuf:"bytes,5,opt,name=agg_sig,json=aggSig,proto3" json:"agg_sig,omitempty"` + // metadata is any arbitrary metadata to attached to the vote. + Metadata []byte `protobuf:"bytes,6,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (m *MsgVotePollAgg) Reset() { *m = MsgVotePollAgg{} } +func (m *MsgVotePollAgg) String() string { return proto.CompactTextString(m) } +func (*MsgVotePollAgg) ProtoMessage() {} +func (*MsgVotePollAgg) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{32} +} +func (m *MsgVotePollAgg) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVotePollAgg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVotePollAgg.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 *MsgVotePollAgg) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVotePollAgg.Merge(m, src) +} +func (m *MsgVotePollAgg) XXX_Size() int { + return m.Size() +} +func (m *MsgVotePollAgg) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVotePollAgg.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVotePollAgg proto.InternalMessageInfo + +func (m *MsgVotePollAgg) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgVotePollAgg) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *MsgVotePollAgg) GetVotes() []Options { + if m != nil { + return m.Votes + } + return nil +} + +func (m *MsgVotePollAgg) GetExpiry() types1.Timestamp { + if m != nil { + return m.Expiry + } + return types1.Timestamp{} +} + +func (m *MsgVotePollAgg) GetAggSig() []byte { + if m != nil { + return m.AggSig + } + return nil +} + +func (m *MsgVotePollAgg) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +// MsgVoteResponse is the Msg/Vote response type. +type MsgVotePollAggResponse struct { +} + +func (m *MsgVotePollAggResponse) Reset() { *m = MsgVotePollAggResponse{} } +func (m *MsgVotePollAggResponse) String() string { return proto.CompactTextString(m) } +func (*MsgVotePollAggResponse) ProtoMessage() {} +func (*MsgVotePollAggResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_b4673626e7797578, []int{33} +} +func (m *MsgVotePollAggResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgVotePollAggResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgVotePollAggResponse.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 *MsgVotePollAggResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgVotePollAggResponse.Merge(m, src) +} +func (m *MsgVotePollAggResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgVotePollAggResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgVotePollAggResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgVotePollAggResponse proto.InternalMessageInfo + +func init() { + proto.RegisterEnum("regen.group.v1alpha1.Exec", Exec_name, Exec_value) + proto.RegisterType((*MsgCreateGroup)(nil), "regen.group.v1alpha1.MsgCreateGroup") + proto.RegisterType((*MsgCreateGroupResponse)(nil), "regen.group.v1alpha1.MsgCreateGroupResponse") + proto.RegisterType((*MsgUpdateGroupMembers)(nil), "regen.group.v1alpha1.MsgUpdateGroupMembers") + proto.RegisterType((*MsgUpdateGroupMembersResponse)(nil), "regen.group.v1alpha1.MsgUpdateGroupMembersResponse") + proto.RegisterType((*MsgUpdateGroupAdmin)(nil), "regen.group.v1alpha1.MsgUpdateGroupAdmin") + proto.RegisterType((*MsgUpdateGroupAdminResponse)(nil), "regen.group.v1alpha1.MsgUpdateGroupAdminResponse") + proto.RegisterType((*MsgUpdateGroupMetadata)(nil), "regen.group.v1alpha1.MsgUpdateGroupMetadata") + proto.RegisterType((*MsgUpdateGroupMetadataResponse)(nil), "regen.group.v1alpha1.MsgUpdateGroupMetadataResponse") + proto.RegisterType((*MsgCreateGroupAccount)(nil), "regen.group.v1alpha1.MsgCreateGroupAccount") + proto.RegisterType((*MsgCreateGroupAccountResponse)(nil), "regen.group.v1alpha1.MsgCreateGroupAccountResponse") + proto.RegisterType((*MsgUpdateGroupAccountAdmin)(nil), "regen.group.v1alpha1.MsgUpdateGroupAccountAdmin") + proto.RegisterType((*MsgUpdateGroupAccountAdminResponse)(nil), "regen.group.v1alpha1.MsgUpdateGroupAccountAdminResponse") + proto.RegisterType((*MsgUpdateGroupAccountDecisionPolicy)(nil), "regen.group.v1alpha1.MsgUpdateGroupAccountDecisionPolicy") + proto.RegisterType((*MsgUpdateGroupAccountDecisionPolicyResponse)(nil), "regen.group.v1alpha1.MsgUpdateGroupAccountDecisionPolicyResponse") + proto.RegisterType((*MsgUpdateGroupAccountMetadata)(nil), "regen.group.v1alpha1.MsgUpdateGroupAccountMetadata") + proto.RegisterType((*MsgUpdateGroupAccountMetadataResponse)(nil), "regen.group.v1alpha1.MsgUpdateGroupAccountMetadataResponse") + proto.RegisterType((*MsgCreateProposal)(nil), "regen.group.v1alpha1.MsgCreateProposal") + proto.RegisterType((*MsgCreateProposalResponse)(nil), "regen.group.v1alpha1.MsgCreateProposalResponse") + proto.RegisterType((*MsgVote)(nil), "regen.group.v1alpha1.MsgVote") + proto.RegisterType((*MsgVoteResponse)(nil), "regen.group.v1alpha1.MsgVoteResponse") + proto.RegisterType((*MsgVoteBasic)(nil), "regen.group.v1alpha1.MsgVoteBasic") + proto.RegisterType((*MsgVoteBasicResponse)(nil), "regen.group.v1alpha1.MsgVoteBasicResponse") + proto.RegisterType((*MsgVoteAgg)(nil), "regen.group.v1alpha1.MsgVoteAgg") + proto.RegisterType((*MsgVoteAggResponse)(nil), "regen.group.v1alpha1.MsgVoteAggResponse") + proto.RegisterType((*MsgExec)(nil), "regen.group.v1alpha1.MsgExec") + proto.RegisterType((*MsgExecResponse)(nil), "regen.group.v1alpha1.MsgExecResponse") + proto.RegisterType((*MsgCreatePoll)(nil), "regen.group.v1alpha1.MsgCreatePoll") + proto.RegisterType((*MsgCreatePollResponse)(nil), "regen.group.v1alpha1.MsgCreatePollResponse") + proto.RegisterType((*MsgVotePoll)(nil), "regen.group.v1alpha1.MsgVotePoll") + proto.RegisterType((*MsgVotePollResponse)(nil), "regen.group.v1alpha1.MsgVotePollResponse") + proto.RegisterType((*MsgVotePollBasic)(nil), "regen.group.v1alpha1.MsgVotePollBasic") + proto.RegisterType((*MsgVotePollBasicResponse)(nil), "regen.group.v1alpha1.MsgVotePollBasicResponse") + proto.RegisterType((*MsgVotePollAgg)(nil), "regen.group.v1alpha1.MsgVotePollAgg") + proto.RegisterType((*MsgVotePollAggResponse)(nil), "regen.group.v1alpha1.MsgVotePollAggResponse") +} + +func init() { proto.RegisterFile("regen/group/v1alpha1/tx.proto", fileDescriptor_b4673626e7797578) } + +var fileDescriptor_b4673626e7797578 = []byte{ + // 1475 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcf, 0x8f, 0xdb, 0xc4, + 0x17, 0x5f, 0x27, 0xd9, 0x64, 0xf7, 0xed, 0x36, 0xdd, 0xba, 0x69, 0x9b, 0xba, 0xdd, 0x24, 0x5f, + 0x77, 0xab, 0xa6, 0xdd, 0xdd, 0xa4, 0xdd, 0xed, 0xa1, 0xed, 0xb7, 0x20, 0xed, 0x6e, 0x17, 0xb4, + 0xa2, 0x4b, 0x8b, 0xdb, 0xa2, 0x82, 0x10, 0x91, 0x63, 0x0f, 0xae, 0xa9, 0xed, 0xb1, 0x62, 0xa7, + 0xdd, 0x1c, 0x38, 0x22, 0x71, 0x42, 0x48, 0x48, 0x80, 0xc4, 0x81, 0xfe, 0x03, 0x70, 0x40, 0x5c, + 0xb9, 0x70, 0xa1, 0xe2, 0xd4, 0x23, 0xa7, 0x0a, 0xb5, 0x37, 0xb8, 0x71, 0x47, 0x42, 0x1e, 0x8f, + 0x27, 0x4e, 0x62, 0x3b, 0xce, 0xb6, 0x02, 0x71, 0xda, 0x9d, 0x99, 0xcf, 0xfb, 0xf5, 0x79, 0x6f, + 0x9e, 0xe7, 0x05, 0x16, 0x3b, 0x48, 0x43, 0x56, 0x53, 0xeb, 0xe0, 0xae, 0xdd, 0x7c, 0x70, 0x41, + 0x36, 0xec, 0x7b, 0xf2, 0x85, 0xa6, 0xbb, 0xd7, 0xb0, 0x3b, 0xd8, 0xc5, 0x7c, 0x89, 0x1c, 0x37, + 0xc8, 0x71, 0x23, 0x38, 0x16, 0x4a, 0x1a, 0xd6, 0x30, 0x01, 0x34, 0xbd, 0xff, 0x7c, 0xac, 0x30, + 0xaf, 0x60, 0xc7, 0xc4, 0x0e, 0x5d, 0x1d, 0xd7, 0x30, 0xd6, 0x0c, 0xd4, 0x24, 0xab, 0x76, 0xf7, + 0x83, 0xa6, 0x6c, 0xf5, 0xe8, 0x51, 0x75, 0xf8, 0xc8, 0xd5, 0x4d, 0xe4, 0xb8, 0xb2, 0x69, 0x53, + 0x40, 0x2d, 0xda, 0xa9, 0x9e, 0x8d, 0xa8, 0x76, 0xf1, 0x6b, 0x0e, 0x8a, 0xbb, 0x8e, 0xb6, 0xd5, + 0x41, 0xb2, 0x8b, 0x5e, 0xf7, 0x70, 0x7c, 0x09, 0xa6, 0x65, 0xd5, 0xd4, 0xad, 0x32, 0x57, 0xe3, + 0xea, 0xb3, 0x92, 0xbf, 0xe0, 0xaf, 0x42, 0xc1, 0x44, 0x66, 0x1b, 0x75, 0x9c, 0x72, 0xa6, 0x96, + 0xad, 0xcf, 0xad, 0x9d, 0x6c, 0x44, 0x85, 0xd4, 0xd8, 0x25, 0xa0, 0xcd, 0xdc, 0xe3, 0xa7, 0xd5, + 0x29, 0x29, 0x10, 0xe1, 0x05, 0x98, 0x31, 0x91, 0x2b, 0xab, 0xb2, 0x2b, 0x97, 0xb3, 0x35, 0xae, + 0x3e, 0x2f, 0xb1, 0x35, 0x7f, 0x1c, 0x66, 0xda, 0x86, 0xd3, 0xc2, 0x96, 0xd1, 0x2b, 0xe7, 0x6a, + 0x5c, 0x7d, 0x46, 0x2a, 0xb4, 0x0d, 0xe7, 0x86, 0x65, 0xf4, 0xc4, 0x75, 0x38, 0x3a, 0xe8, 0x9c, + 0x84, 0x1c, 0x1b, 0x5b, 0x0e, 0xf2, 0x84, 0x88, 0xe1, 0x96, 0xae, 0x12, 0x3f, 0x73, 0x52, 0x81, + 0xac, 0x77, 0x54, 0xf1, 0x73, 0x0e, 0x8e, 0xec, 0x3a, 0xda, 0x1d, 0x5b, 0x0d, 0xa4, 0x76, 0xa9, + 0x17, 0xd1, 0x91, 0x85, 0x55, 0x65, 0x06, 0x54, 0xf1, 0x3b, 0x50, 0xf4, 0x23, 0x68, 0x75, 0x89, + 0x36, 0xa7, 0x9c, 0x4d, 0x1d, 0xfb, 0x01, 0x5f, 0xd2, 0x77, 0xc3, 0x11, 0xab, 0xb0, 0x18, 0xe9, + 0x54, 0x10, 0x91, 0xa8, 0xc0, 0xe1, 0x41, 0xc0, 0x06, 0xf1, 0x6e, 0x62, 0x9f, 0x4f, 0xc0, 0xac, + 0x85, 0x1e, 0xb6, 0x7c, 0xa1, 0x2c, 0x11, 0x9a, 0xb1, 0xd0, 0x43, 0xa2, 0x4d, 0x5c, 0x84, 0x13, + 0x11, 0x46, 0x98, 0x0f, 0x88, 0xf0, 0x3d, 0xe0, 0x24, 0x4d, 0xd2, 0xc4, 0x6e, 0x24, 0x64, 0x5c, + 0xac, 0x41, 0x25, 0xda, 0x0c, 0x73, 0xe4, 0x47, 0x3f, 0x87, 0xa1, 0xcc, 0x6f, 0x28, 0x0a, 0xee, + 0x5a, 0xee, 0x4b, 0x75, 0x84, 0x7f, 0x0b, 0x0e, 0xaa, 0x48, 0xd1, 0x1d, 0x1d, 0x5b, 0x2d, 0x1b, + 0x1b, 0xba, 0xe2, 0x57, 0xe0, 0xdc, 0x5a, 0xa9, 0xe1, 0x5f, 0xad, 0x46, 0x70, 0xb5, 0x1a, 0x1b, + 0x56, 0x6f, 0x93, 0xff, 0xe5, 0x87, 0xd5, 0xe2, 0x35, 0x2a, 0x70, 0x93, 0xe0, 0xa5, 0xa2, 0x3a, + 0xb0, 0xbe, 0x92, 0xfb, 0xe4, 0x51, 0x75, 0x4a, 0xbc, 0x4c, 0xb2, 0x3d, 0xea, 0x3e, 0xab, 0xdf, + 0x32, 0x14, 0x64, 0x55, 0xed, 0x20, 0xc7, 0xa1, 0x81, 0x04, 0x4b, 0x51, 0x07, 0x61, 0x28, 0x45, + 0xbe, 0x68, 0x52, 0x39, 0x84, 0xb4, 0x65, 0x06, 0xb4, 0x25, 0x57, 0xc3, 0x12, 0x88, 0xf1, 0xa6, + 0x58, 0x2e, 0xbe, 0xe3, 0xe0, 0x54, 0x24, 0x6c, 0x90, 0x89, 0x89, 0x5d, 0x8b, 0x20, 0x3f, 0xfb, + 0x52, 0xc8, 0x5f, 0x85, 0xe5, 0x14, 0xfe, 0xb2, 0xf8, 0xee, 0x0f, 0xdf, 0x4c, 0x0a, 0x1f, 0x53, + 0xfb, 0xf1, 0x81, 0x25, 0x95, 0xfe, 0x19, 0x38, 0x9d, 0x68, 0x8c, 0x79, 0xf5, 0x33, 0x07, 0x87, + 0x58, 0x09, 0xdd, 0xec, 0x60, 0x1b, 0x3b, 0xb2, 0x11, 0x5f, 0x36, 0xfc, 0x49, 0x98, 0xb5, 0x09, + 0x2a, 0xe8, 0xd0, 0xb3, 0x52, 0x7f, 0x23, 0xf1, 0x12, 0xd4, 0x21, 0x67, 0x3a, 0x9a, 0x53, 0xce, + 0x91, 0xd6, 0x16, 0x49, 0xbe, 0x44, 0x10, 0x7c, 0x03, 0x72, 0x68, 0x0f, 0x29, 0xe5, 0xe9, 0x1a, + 0x57, 0x2f, 0xae, 0x09, 0xd1, 0x4d, 0x70, 0x7b, 0x0f, 0x29, 0x12, 0xc1, 0xd1, 0x74, 0x5c, 0x85, + 0xe3, 0x23, 0x81, 0xb0, 0x7b, 0x50, 0x85, 0x39, 0x9b, 0xee, 0xf5, 0x5b, 0x39, 0x04, 0x5b, 0x3b, + 0xaa, 0xf8, 0x13, 0x07, 0x85, 0x5d, 0x47, 0x7b, 0x1b, 0xbb, 0xe3, 0xc1, 0x5e, 0xa6, 0x1e, 0x60, + 0x17, 0x75, 0x68, 0x46, 0xfc, 0x05, 0x7f, 0x11, 0xf2, 0xca, 0x3d, 0xac, 0x2b, 0x88, 0x84, 0x5e, + 0x8c, 0xeb, 0xde, 0x5b, 0x04, 0x23, 0x51, 0xec, 0x00, 0x65, 0xb9, 0x21, 0xca, 0x26, 0x24, 0x42, + 0x3c, 0x04, 0x07, 0x69, 0x0c, 0x2c, 0xbf, 0xdf, 0x70, 0x30, 0x4f, 0xf7, 0x36, 0x65, 0x47, 0x57, + 0xc6, 0x07, 0xd7, 0x0f, 0x23, 0x33, 0x41, 0x18, 0x97, 0x20, 0x8f, 0xf6, 0x6c, 0xbd, 0x13, 0x5c, + 0x2e, 0x61, 0x24, 0xbf, 0xb7, 0x83, 0x47, 0x03, 0xfd, 0x70, 0x51, 0xbc, 0xf8, 0x6d, 0x06, 0x4a, + 0x61, 0x0f, 0x53, 0xe7, 0xec, 0x9f, 0xf6, 0xb4, 0x9f, 0xf6, 0x5c, 0x38, 0xed, 0xef, 0x41, 0xc1, + 0xee, 0xb6, 0x5b, 0xf7, 0x51, 0x8f, 0xe4, 0x29, 0xae, 0xaf, 0xac, 0xfe, 0xfe, 0xb4, 0x5a, 0xb2, + 0xbb, 0x6d, 0x43, 0x57, 0x3c, 0xec, 0x0a, 0x36, 0x75, 0x17, 0x99, 0xb6, 0xdb, 0xfb, 0xf3, 0x69, + 0xf5, 0x50, 0x4f, 0x36, 0x8d, 0x2b, 0x62, 0xff, 0x54, 0x94, 0xf2, 0x76, 0xb7, 0xfd, 0x06, 0xea, + 0xf1, 0x0b, 0x90, 0x75, 0x74, 0xad, 0x9c, 0x27, 0x95, 0xe1, 0xfd, 0x2b, 0x7e, 0x95, 0x01, 0xa0, + 0x7c, 0x6d, 0x68, 0x1a, 0x7f, 0x14, 0xf2, 0x0e, 0xb2, 0x54, 0xd4, 0xa1, 0x37, 0x95, 0xae, 0x86, + 0xd9, 0xcb, 0x8c, 0xb0, 0xb7, 0xe6, 0x47, 0xe3, 0xbf, 0x35, 0xc6, 0x91, 0xe7, 0x43, 0x43, 0xdc, + 0xe5, 0x26, 0xe4, 0xee, 0x18, 0x14, 0x64, 0x4d, 0x6b, 0x79, 0xb1, 0x4c, 0x93, 0x58, 0xf2, 0xb2, + 0xa6, 0xdd, 0xd2, 0xb5, 0x81, 0xfa, 0xcf, 0xc7, 0xd4, 0x7f, 0x21, 0x65, 0xfd, 0x97, 0x80, 0xef, + 0x33, 0xc3, 0xae, 0xc0, 0x26, 0xb9, 0xd9, 0x1e, 0x6c, 0x7c, 0x49, 0x79, 0x6c, 0xea, 0x9a, 0xc5, + 0xae, 0x36, 0x5d, 0xd1, 0x9b, 0x45, 0x4c, 0x05, 0x6a, 0xbf, 0xc8, 0xc0, 0x81, 0x7e, 0xc3, 0xc1, + 0x86, 0x91, 0xf0, 0x58, 0xf4, 0x4a, 0xc7, 0xd5, 0x5d, 0x03, 0x05, 0x1d, 0x83, 0x2c, 0xf8, 0x57, + 0xa0, 0x80, 0x6d, 0x57, 0xc7, 0x96, 0x43, 0x6b, 0x71, 0x31, 0x3a, 0xc4, 0x1b, 0x3e, 0x28, 0x78, + 0xed, 0x52, 0x19, 0xaf, 0x4b, 0x2b, 0x9e, 0x75, 0x1c, 0x54, 0x64, 0xb0, 0xe4, 0x17, 0x01, 0xbc, + 0x84, 0xb5, 0x0c, 0xdd, 0xd4, 0x5d, 0x42, 0xf8, 0xb4, 0x34, 0xeb, 0xed, 0x5c, 0xf7, 0x36, 0x12, + 0x39, 0xbf, 0x02, 0x05, 0xef, 0x79, 0x8f, 0xbb, 0x2e, 0xa1, 0x3d, 0x4d, 0x8e, 0x03, 0x01, 0xda, + 0x88, 0xcf, 0x87, 0xde, 0x54, 0x1e, 0x2f, 0xec, 0x42, 0x1f, 0x83, 0x82, 0x8d, 0x8d, 0x10, 0xf3, + 0x79, 0x6f, 0xb9, 0xa3, 0x8a, 0x5f, 0x72, 0x30, 0x47, 0x13, 0x47, 0x88, 0x8c, 0x03, 0xc6, 0x34, + 0xde, 0x17, 0xa4, 0x31, 0xa1, 0x03, 0x8b, 0x47, 0xc8, 0x6b, 0x39, 0x70, 0x8c, 0xe5, 0xfe, 0x23, + 0x58, 0x08, 0x6d, 0xfb, 0x8d, 0x35, 0xd6, 0xe9, 0xa3, 0x90, 0xf7, 0x4d, 0x05, 0x35, 0xe5, 0xaf, + 0x5e, 0xa0, 0x65, 0x7e, 0x9f, 0x81, 0xf2, 0xb0, 0xfd, 0xb1, 0x2c, 0x87, 0x69, 0xca, 0xec, 0x83, + 0xa6, 0xff, 0x7a, 0xdf, 0xfc, 0xc3, 0x1f, 0x41, 0x03, 0xd2, 0x92, 0x7a, 0x67, 0x88, 0xc2, 0xcc, + 0x00, 0x85, 0x97, 0xc3, 0x3d, 0x33, 0x25, 0x81, 0xff, 0x4a, 0xeb, 0x14, 0xcb, 0x64, 0xc4, 0x0a, + 0x05, 0x1b, 0xd4, 0xc7, 0xb9, 0x73, 0x90, 0x23, 0xbd, 0xb0, 0x04, 0x0b, 0xdb, 0x77, 0xb7, 0xb7, + 0x5a, 0x77, 0xde, 0xbc, 0x75, 0x73, 0x7b, 0x6b, 0xe7, 0xb5, 0x9d, 0xed, 0x6b, 0x0b, 0x53, 0xfc, + 0x3c, 0xcc, 0x90, 0xdd, 0xdb, 0xd2, 0x3b, 0x0b, 0xdc, 0xda, 0x5f, 0xf3, 0x90, 0xdd, 0x75, 0x34, + 0x5e, 0x86, 0xb9, 0xf0, 0xe8, 0xbe, 0x14, 0x33, 0x97, 0x0e, 0x8c, 0x22, 0xc2, 0x4a, 0x1a, 0x14, + 0x2b, 0xdb, 0x07, 0xc0, 0x47, 0x8c, 0xd2, 0xcb, 0xb1, 0x3a, 0x46, 0xc1, 0xc2, 0xfa, 0x04, 0x60, + 0x66, 0xd7, 0x86, 0x85, 0x91, 0x61, 0xf8, 0x6c, 0x1a, 0x45, 0x04, 0x2a, 0x5c, 0x48, 0x0d, 0x65, + 0x16, 0x7b, 0x70, 0x38, 0x6a, 0xf4, 0x5d, 0x49, 0xe7, 0xbd, 0x8f, 0x16, 0x2e, 0x4e, 0x82, 0x0e, + 0x93, 0x1c, 0x31, 0xeb, 0x2e, 0xa7, 0x49, 0x14, 0x05, 0x27, 0x90, 0x9c, 0x30, 0x86, 0x7e, 0xcc, + 0xc1, 0xb1, 0xb8, 0x51, 0xf3, 0x7c, 0x2a, 0x06, 0x43, 0x12, 0xc2, 0xa5, 0x49, 0x25, 0x98, 0x1f, + 0x8f, 0x38, 0xa8, 0x8d, 0x1d, 0x30, 0x2f, 0x4f, 0xa0, 0x7e, 0x50, 0x54, 0xd8, 0xd8, 0xb7, 0x28, + 0x73, 0xf1, 0x53, 0x0e, 0x84, 0x84, 0x21, 0x71, 0x7d, 0x02, 0x0b, 0xac, 0x58, 0xfe, 0xbf, 0x0f, + 0x21, 0xe6, 0xd0, 0x87, 0x50, 0x1c, 0x9a, 0x0e, 0xcf, 0x8c, 0x29, 0x81, 0x00, 0x28, 0x34, 0x53, + 0x02, 0x99, 0xad, 0xeb, 0x90, 0x23, 0x13, 0xd8, 0x62, 0xac, 0xa0, 0x77, 0x2c, 0x9c, 0x4e, 0x3c, + 0x66, 0xda, 0xee, 0x40, 0x21, 0x78, 0x25, 0xd7, 0x12, 0x25, 0x36, 0x34, 0x4d, 0xa8, 0x8f, 0x43, + 0x84, 0x9d, 0x24, 0x0d, 0x34, 0xde, 0x49, 0xef, 0x38, 0xc1, 0xc9, 0xf0, 0x33, 0x92, 0x7f, 0x1f, + 0x20, 0xf4, 0x84, 0x3c, 0x35, 0x8e, 0x31, 0x6c, 0x18, 0xc2, 0x72, 0x0a, 0x10, 0xd3, 0x7f, 0x17, + 0x66, 0xd8, 0xbb, 0xea, 0x7f, 0x89, 0x31, 0x12, 0xdd, 0x67, 0xc7, 0x42, 0x98, 0x66, 0x19, 0xe6, + 0xc2, 0x1f, 0xd3, 0xa5, 0xb1, 0x92, 0x1e, 0xcd, 0x2b, 0x69, 0x50, 0x81, 0x89, 0xcd, 0x57, 0x1f, + 0x3f, 0xab, 0x70, 0x4f, 0x9e, 0x55, 0xb8, 0xdf, 0x9e, 0x55, 0xb8, 0xcf, 0x9e, 0x57, 0xa6, 0x9e, + 0x3c, 0xaf, 0x4c, 0xfd, 0xfa, 0xbc, 0x32, 0xf5, 0xee, 0x92, 0xa6, 0xbb, 0xf7, 0xba, 0xed, 0x86, + 0x82, 0xcd, 0xa6, 0xff, 0x3b, 0x36, 0xfd, 0xb3, 0xea, 0xa8, 0xf7, 0x9b, 0x7b, 0xfe, 0x6f, 0xd1, + 0xed, 0x3c, 0xf9, 0xb8, 0xae, 0xff, 0x1d, 0x00, 0x00, 0xff, 0xff, 0x48, 0xf8, 0x8f, 0x4a, 0x36, + 0x17, 0x00, 0x00, +} + +// 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 { + // CreateGroup creates a new group with an admin account address, a list of members and some optional metadata. + CreateGroup(ctx context.Context, in *MsgCreateGroup, opts ...grpc.CallOption) (*MsgCreateGroupResponse, error) + // UpdateGroupMembers updates the group members with given group id and admin address. + UpdateGroupMembers(ctx context.Context, in *MsgUpdateGroupMembers, opts ...grpc.CallOption) (*MsgUpdateGroupMembersResponse, error) + // UpdateGroupAdmin updates the group admin with given group id and previous admin address. + UpdateGroupAdmin(ctx context.Context, in *MsgUpdateGroupAdmin, opts ...grpc.CallOption) (*MsgUpdateGroupAdminResponse, error) + // UpdateGroupMetadata updates the group metadata with given group id and admin address. + UpdateGroupMetadata(ctx context.Context, in *MsgUpdateGroupMetadata, opts ...grpc.CallOption) (*MsgUpdateGroupMetadataResponse, error) + // CreateGroupAccount creates a new group account using given DecisionPolicy. + CreateGroupAccount(ctx context.Context, in *MsgCreateGroupAccount, opts ...grpc.CallOption) (*MsgCreateGroupAccountResponse, error) + // UpdateGroupAccountAdmin updates a group account admin. + UpdateGroupAccountAdmin(ctx context.Context, in *MsgUpdateGroupAccountAdmin, opts ...grpc.CallOption) (*MsgUpdateGroupAccountAdminResponse, error) + // UpdateGroupAccountDecisionPolicy allows a group account decision policy to be updated. + UpdateGroupAccountDecisionPolicy(ctx context.Context, in *MsgUpdateGroupAccountDecisionPolicy, opts ...grpc.CallOption) (*MsgUpdateGroupAccountDecisionPolicyResponse, error) + // UpdateGroupAccountMetadata updates a group account metadata. + UpdateGroupAccountMetadata(ctx context.Context, in *MsgUpdateGroupAccountMetadata, opts ...grpc.CallOption) (*MsgUpdateGroupAccountMetadataResponse, error) + // CreateProposal submits a new proposal. + CreateProposal(ctx context.Context, in *MsgCreateProposal, opts ...grpc.CallOption) (*MsgCreateProposalResponse, error) + // Vote allows a voter to vote on a proposal. + Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) + // VoteAgg allows a sender to submit a set of votes + VoteAgg(ctx context.Context, in *MsgVoteAgg, opts ...grpc.CallOption) (*MsgVoteAggResponse, error) + // Exec executes a proposal. + Exec(ctx context.Context, in *MsgExec, opts ...grpc.CallOption) (*MsgExecResponse, error) + // CreatePoll submits a new poll. + CreatePoll(ctx context.Context, in *MsgCreatePoll, opts ...grpc.CallOption) (*MsgCreatePollResponse, error) + // VotePoll allows a voter to vote on a poll. + VotePoll(ctx context.Context, in *MsgVotePoll, opts ...grpc.CallOption) (*MsgVotePollResponse, error) + // VotePollAgg allows a sender to submit a set of votes + VotePollAgg(ctx context.Context, in *MsgVotePollAgg, opts ...grpc.CallOption) (*MsgVotePollAggResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) CreateGroup(ctx context.Context, in *MsgCreateGroup, opts ...grpc.CallOption) (*MsgCreateGroupResponse, error) { + out := new(MsgCreateGroupResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/CreateGroup", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateGroupMembers(ctx context.Context, in *MsgUpdateGroupMembers, opts ...grpc.CallOption) (*MsgUpdateGroupMembersResponse, error) { + out := new(MsgUpdateGroupMembersResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/UpdateGroupMembers", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateGroupAdmin(ctx context.Context, in *MsgUpdateGroupAdmin, opts ...grpc.CallOption) (*MsgUpdateGroupAdminResponse, error) { + out := new(MsgUpdateGroupAdminResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/UpdateGroupAdmin", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateGroupMetadata(ctx context.Context, in *MsgUpdateGroupMetadata, opts ...grpc.CallOption) (*MsgUpdateGroupMetadataResponse, error) { + out := new(MsgUpdateGroupMetadataResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/UpdateGroupMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) CreateGroupAccount(ctx context.Context, in *MsgCreateGroupAccount, opts ...grpc.CallOption) (*MsgCreateGroupAccountResponse, error) { + out := new(MsgCreateGroupAccountResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/CreateGroupAccount", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateGroupAccountAdmin(ctx context.Context, in *MsgUpdateGroupAccountAdmin, opts ...grpc.CallOption) (*MsgUpdateGroupAccountAdminResponse, error) { + out := new(MsgUpdateGroupAccountAdminResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/UpdateGroupAccountAdmin", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateGroupAccountDecisionPolicy(ctx context.Context, in *MsgUpdateGroupAccountDecisionPolicy, opts ...grpc.CallOption) (*MsgUpdateGroupAccountDecisionPolicyResponse, error) { + out := new(MsgUpdateGroupAccountDecisionPolicyResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/UpdateGroupAccountDecisionPolicy", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) UpdateGroupAccountMetadata(ctx context.Context, in *MsgUpdateGroupAccountMetadata, opts ...grpc.CallOption) (*MsgUpdateGroupAccountMetadataResponse, error) { + out := new(MsgUpdateGroupAccountMetadataResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/UpdateGroupAccountMetadata", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) CreateProposal(ctx context.Context, in *MsgCreateProposal, opts ...grpc.CallOption) (*MsgCreateProposalResponse, error) { + out := new(MsgCreateProposalResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/CreateProposal", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Vote(ctx context.Context, in *MsgVote, opts ...grpc.CallOption) (*MsgVoteResponse, error) { + out := new(MsgVoteResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/Vote", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) VoteAgg(ctx context.Context, in *MsgVoteAgg, opts ...grpc.CallOption) (*MsgVoteAggResponse, error) { + out := new(MsgVoteAggResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/VoteAgg", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) Exec(ctx context.Context, in *MsgExec, opts ...grpc.CallOption) (*MsgExecResponse, error) { + out := new(MsgExecResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/Exec", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) CreatePoll(ctx context.Context, in *MsgCreatePoll, opts ...grpc.CallOption) (*MsgCreatePollResponse, error) { + out := new(MsgCreatePollResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/CreatePoll", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) VotePoll(ctx context.Context, in *MsgVotePoll, opts ...grpc.CallOption) (*MsgVotePollResponse, error) { + out := new(MsgVotePollResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/VotePoll", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *msgClient) VotePollAgg(ctx context.Context, in *MsgVotePollAgg, opts ...grpc.CallOption) (*MsgVotePollAggResponse, error) { + out := new(MsgVotePollAggResponse) + err := c.cc.Invoke(ctx, "/regen.group.v1alpha1.Msg/VotePollAgg", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // CreateGroup creates a new group with an admin account address, a list of members and some optional metadata. + CreateGroup(context.Context, *MsgCreateGroup) (*MsgCreateGroupResponse, error) + // UpdateGroupMembers updates the group members with given group id and admin address. + UpdateGroupMembers(context.Context, *MsgUpdateGroupMembers) (*MsgUpdateGroupMembersResponse, error) + // UpdateGroupAdmin updates the group admin with given group id and previous admin address. + UpdateGroupAdmin(context.Context, *MsgUpdateGroupAdmin) (*MsgUpdateGroupAdminResponse, error) + // UpdateGroupMetadata updates the group metadata with given group id and admin address. + UpdateGroupMetadata(context.Context, *MsgUpdateGroupMetadata) (*MsgUpdateGroupMetadataResponse, error) + // CreateGroupAccount creates a new group account using given DecisionPolicy. + CreateGroupAccount(context.Context, *MsgCreateGroupAccount) (*MsgCreateGroupAccountResponse, error) + // UpdateGroupAccountAdmin updates a group account admin. + UpdateGroupAccountAdmin(context.Context, *MsgUpdateGroupAccountAdmin) (*MsgUpdateGroupAccountAdminResponse, error) + // UpdateGroupAccountDecisionPolicy allows a group account decision policy to be updated. + UpdateGroupAccountDecisionPolicy(context.Context, *MsgUpdateGroupAccountDecisionPolicy) (*MsgUpdateGroupAccountDecisionPolicyResponse, error) + // UpdateGroupAccountMetadata updates a group account metadata. + UpdateGroupAccountMetadata(context.Context, *MsgUpdateGroupAccountMetadata) (*MsgUpdateGroupAccountMetadataResponse, error) + // CreateProposal submits a new proposal. + CreateProposal(context.Context, *MsgCreateProposal) (*MsgCreateProposalResponse, error) + // Vote allows a voter to vote on a proposal. + Vote(context.Context, *MsgVote) (*MsgVoteResponse, error) + // VoteAgg allows a sender to submit a set of votes + VoteAgg(context.Context, *MsgVoteAgg) (*MsgVoteAggResponse, error) + // Exec executes a proposal. + Exec(context.Context, *MsgExec) (*MsgExecResponse, error) + // CreatePoll submits a new poll. + CreatePoll(context.Context, *MsgCreatePoll) (*MsgCreatePollResponse, error) + // VotePoll allows a voter to vote on a poll. + VotePoll(context.Context, *MsgVotePoll) (*MsgVotePollResponse, error) + // VotePollAgg allows a sender to submit a set of votes + VotePollAgg(context.Context, *MsgVotePollAgg) (*MsgVotePollAggResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) CreateGroup(ctx context.Context, req *MsgCreateGroup) (*MsgCreateGroupResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateGroup not implemented") +} +func (*UnimplementedMsgServer) UpdateGroupMembers(ctx context.Context, req *MsgUpdateGroupMembers) (*MsgUpdateGroupMembersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateGroupMembers not implemented") +} +func (*UnimplementedMsgServer) UpdateGroupAdmin(ctx context.Context, req *MsgUpdateGroupAdmin) (*MsgUpdateGroupAdminResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateGroupAdmin not implemented") +} +func (*UnimplementedMsgServer) UpdateGroupMetadata(ctx context.Context, req *MsgUpdateGroupMetadata) (*MsgUpdateGroupMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateGroupMetadata not implemented") +} +func (*UnimplementedMsgServer) CreateGroupAccount(ctx context.Context, req *MsgCreateGroupAccount) (*MsgCreateGroupAccountResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateGroupAccount not implemented") +} +func (*UnimplementedMsgServer) UpdateGroupAccountAdmin(ctx context.Context, req *MsgUpdateGroupAccountAdmin) (*MsgUpdateGroupAccountAdminResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateGroupAccountAdmin not implemented") +} +func (*UnimplementedMsgServer) UpdateGroupAccountDecisionPolicy(ctx context.Context, req *MsgUpdateGroupAccountDecisionPolicy) (*MsgUpdateGroupAccountDecisionPolicyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateGroupAccountDecisionPolicy not implemented") +} +func (*UnimplementedMsgServer) UpdateGroupAccountMetadata(ctx context.Context, req *MsgUpdateGroupAccountMetadata) (*MsgUpdateGroupAccountMetadataResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateGroupAccountMetadata not implemented") +} +func (*UnimplementedMsgServer) CreateProposal(ctx context.Context, req *MsgCreateProposal) (*MsgCreateProposalResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateProposal not implemented") +} +func (*UnimplementedMsgServer) Vote(ctx context.Context, req *MsgVote) (*MsgVoteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Vote not implemented") +} +func (*UnimplementedMsgServer) VoteAgg(ctx context.Context, req *MsgVoteAgg) (*MsgVoteAggResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VoteAgg not implemented") +} +func (*UnimplementedMsgServer) Exec(ctx context.Context, req *MsgExec) (*MsgExecResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Exec not implemented") +} +func (*UnimplementedMsgServer) CreatePoll(ctx context.Context, req *MsgCreatePoll) (*MsgCreatePollResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreatePoll not implemented") +} +func (*UnimplementedMsgServer) VotePoll(ctx context.Context, req *MsgVotePoll) (*MsgVotePollResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VotePoll not implemented") +} +func (*UnimplementedMsgServer) VotePollAgg(ctx context.Context, req *MsgVotePollAgg) (*MsgVotePollAggResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VotePollAgg not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_CreateGroup_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateGroup) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateGroup(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/CreateGroup", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateGroup(ctx, req.(*MsgCreateGroup)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateGroupMembers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateGroupMembers) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateGroupMembers(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/UpdateGroupMembers", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateGroupMembers(ctx, req.(*MsgUpdateGroupMembers)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateGroupAdmin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateGroupAdmin) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateGroupAdmin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/UpdateGroupAdmin", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateGroupAdmin(ctx, req.(*MsgUpdateGroupAdmin)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateGroupMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateGroupMetadata) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateGroupMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/UpdateGroupMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateGroupMetadata(ctx, req.(*MsgUpdateGroupMetadata)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_CreateGroupAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateGroupAccount) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateGroupAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/CreateGroupAccount", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateGroupAccount(ctx, req.(*MsgCreateGroupAccount)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateGroupAccountAdmin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateGroupAccountAdmin) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateGroupAccountAdmin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/UpdateGroupAccountAdmin", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateGroupAccountAdmin(ctx, req.(*MsgUpdateGroupAccountAdmin)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateGroupAccountDecisionPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateGroupAccountDecisionPolicy) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateGroupAccountDecisionPolicy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/UpdateGroupAccountDecisionPolicy", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateGroupAccountDecisionPolicy(ctx, req.(*MsgUpdateGroupAccountDecisionPolicy)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_UpdateGroupAccountMetadata_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgUpdateGroupAccountMetadata) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).UpdateGroupAccountMetadata(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/UpdateGroupAccountMetadata", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).UpdateGroupAccountMetadata(ctx, req.(*MsgUpdateGroupAccountMetadata)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_CreateProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateProposal) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateProposal(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/CreateProposal", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateProposal(ctx, req.(*MsgCreateProposal)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Vote_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVote) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Vote(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/Vote", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Vote(ctx, req.(*MsgVote)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_VoteAgg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVoteAgg) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).VoteAgg(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/VoteAgg", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).VoteAgg(ctx, req.(*MsgVoteAgg)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_Exec_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgExec) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).Exec(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/Exec", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).Exec(ctx, req.(*MsgExec)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_CreatePoll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreatePoll) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreatePoll(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/CreatePoll", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreatePoll(ctx, req.(*MsgCreatePoll)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_VotePoll_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVotePoll) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).VotePoll(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/VotePoll", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).VotePoll(ctx, req.(*MsgVotePoll)) + } + return interceptor(ctx, in, info, handler) +} + +func _Msg_VotePollAgg_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgVotePollAgg) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).VotePollAgg(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/regen.group.v1alpha1.Msg/VotePollAgg", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).VotePollAgg(ctx, req.(*MsgVotePollAgg)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "regen.group.v1alpha1.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateGroup", + Handler: _Msg_CreateGroup_Handler, + }, + { + MethodName: "UpdateGroupMembers", + Handler: _Msg_UpdateGroupMembers_Handler, + }, + { + MethodName: "UpdateGroupAdmin", + Handler: _Msg_UpdateGroupAdmin_Handler, + }, + { + MethodName: "UpdateGroupMetadata", + Handler: _Msg_UpdateGroupMetadata_Handler, + }, + { + MethodName: "CreateGroupAccount", + Handler: _Msg_CreateGroupAccount_Handler, + }, + { + MethodName: "UpdateGroupAccountAdmin", + Handler: _Msg_UpdateGroupAccountAdmin_Handler, + }, + { + MethodName: "UpdateGroupAccountDecisionPolicy", + Handler: _Msg_UpdateGroupAccountDecisionPolicy_Handler, + }, + { + MethodName: "UpdateGroupAccountMetadata", + Handler: _Msg_UpdateGroupAccountMetadata_Handler, + }, + { + MethodName: "CreateProposal", + Handler: _Msg_CreateProposal_Handler, + }, + { + MethodName: "Vote", + Handler: _Msg_Vote_Handler, + }, + { + MethodName: "VoteAgg", + Handler: _Msg_VoteAgg_Handler, + }, + { + MethodName: "Exec", + Handler: _Msg_Exec_Handler, + }, + { + MethodName: "CreatePoll", + Handler: _Msg_CreatePoll_Handler, + }, + { + MethodName: "VotePoll", + Handler: _Msg_VotePoll_Handler, + }, + { + MethodName: "VotePollAgg", + Handler: _Msg_VotePollAgg_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "regen/group/v1alpha1/tx.proto", +} + +func (m *MsgCreateGroup) 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 *MsgCreateGroup) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateGroup) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlsOnly { + i-- + if m.BlsOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x20 + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Members[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateGroupResponse) 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 *MsgCreateGroupResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateGroupResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.GroupId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupMembers) 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 *MsgUpdateGroupMembers) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupMembers) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.MemberUpdates) > 0 { + for iNdEx := len(m.MemberUpdates) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.MemberUpdates[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.GroupId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupMembersResponse) 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 *MsgUpdateGroupMembersResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupMembersResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAdmin) 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 *MsgUpdateGroupAdmin) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAdmin) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.NewAdmin) > 0 { + i -= len(m.NewAdmin) + copy(dAtA[i:], m.NewAdmin) + i = encodeVarintTx(dAtA, i, uint64(len(m.NewAdmin))) + i-- + dAtA[i] = 0x1a + } + if m.GroupId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAdminResponse) 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 *MsgUpdateGroupAdminResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAdminResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupMetadata) 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 *MsgUpdateGroupMetadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if m.GroupId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupMetadataResponse) 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 *MsgUpdateGroupMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgCreateGroupAccount) 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 *MsgCreateGroupAccount) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateGroupAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.DecisionPolicy != nil { + { + size, err := m.DecisionPolicy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if m.GroupId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateGroupAccountResponse) 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 *MsgCreateGroupAccountResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateGroupAccountResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAccountAdmin) 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 *MsgUpdateGroupAccountAdmin) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAccountAdmin) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.NewAdmin) > 0 { + i -= len(m.NewAdmin) + copy(dAtA[i:], m.NewAdmin) + i = encodeVarintTx(dAtA, i, uint64(len(m.NewAdmin))) + i-- + dAtA[i] = 0x1a + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAccountAdminResponse) 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 *MsgUpdateGroupAccountAdminResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAccountAdminResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAccountDecisionPolicy) 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 *MsgUpdateGroupAccountDecisionPolicy) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAccountDecisionPolicy) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.DecisionPolicy != nil { + { + size, err := m.DecisionPolicy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) 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 *MsgUpdateGroupAccountDecisionPolicyResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAccountMetadata) 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 *MsgUpdateGroupAccountMetadata) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAccountMetadata) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTx(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateGroupAccountMetadataResponse) 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 *MsgUpdateGroupAccountMetadataResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateGroupAccountMetadataResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgCreateProposal) 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 *MsgCreateProposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateProposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Exec != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Exec)) + i-- + dAtA[i] = 0x28 + } + if len(m.Msgs) > 0 { + for iNdEx := len(m.Msgs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Msgs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if len(m.Proposers) > 0 { + for iNdEx := len(m.Proposers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Proposers[iNdEx]) + copy(dAtA[i:], m.Proposers[iNdEx]) + i = encodeVarintTx(dAtA, i, uint64(len(m.Proposers[iNdEx]))) + i-- + dAtA[i] = 0x12 + } + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTx(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateProposalResponse) 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 *MsgCreateProposalResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateProposalResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVote) 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 *MsgVote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Exec != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Exec)) + i-- + dAtA[i] = 0x28 + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x22 + } + if m.Choice != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Choice)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVoteResponse) 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 *MsgVoteResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgVoteBasic) 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 *MsgVoteBasic) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteBasic) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Expiry.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Choice != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Choice)) + i-- + dAtA[i] = 0x10 + } + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVoteBasicResponse) 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 *MsgVoteBasicResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteBasicResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Sig) > 0 { + i -= len(m.Sig) + copy(dAtA[i:], m.Sig) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sig))) + i-- + dAtA[i] = 0x32 + } + if m.PubKey != nil { + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Expiry.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Choice != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Choice)) + i-- + dAtA[i] = 0x10 + } + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVoteAgg) 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 *MsgVoteAgg) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteAgg) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Exec != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.Exec)) + i-- + dAtA[i] = 0x38 + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x32 + } + if len(m.AggSig) > 0 { + i -= len(m.AggSig) + copy(dAtA[i:], m.AggSig) + i = encodeVarintTx(dAtA, i, uint64(len(m.AggSig))) + i-- + dAtA[i] = 0x2a + } + { + size, err := m.Expiry.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Votes) > 0 { + dAtA8 := make([]byte, len(m.Votes)*10) + var j7 int + for _, num := range m.Votes { + for num >= 1<<7 { + dAtA8[j7] = uint8(uint64(num)&0x7f | 0x80) + num >>= 7 + j7++ + } + dAtA8[j7] = uint8(num) + j7++ + } + i -= j7 + copy(dAtA[i:], dAtA8[:j7]) + i = encodeVarintTx(dAtA, i, uint64(j7)) + i-- + dAtA[i] = 0x1a + } + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgVoteAggResponse) 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 *MsgVoteAggResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVoteAggResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgExec) 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 *MsgExec) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgExec) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Signer) > 0 { + i -= len(m.Signer) + copy(dAtA[i:], m.Signer) + i = encodeVarintTx(dAtA, i, uint64(len(m.Signer))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgExecResponse) 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 *MsgExecResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgExecResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgCreatePoll) 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 *MsgCreatePoll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreatePoll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Timeout.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x32 + } + if m.VoteLimit != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.VoteLimit)) + i-- + dAtA[i] = 0x28 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTx(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Options.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintTx(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgCreatePollResponse) 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 *MsgCreatePollResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreatePollResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.PollId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVotePoll) 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 *MsgVotePoll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVotePoll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Options.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.PollId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVotePollResponse) 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 *MsgVotePollResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVotePollResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func (m *MsgVotePollBasic) 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 *MsgVotePollBasic) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVotePollBasic) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Expiry.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Option) > 0 { + i -= len(m.Option) + copy(dAtA[i:], m.Option) + i = encodeVarintTx(dAtA, i, uint64(len(m.Option))) + i-- + dAtA[i] = 0x12 + } + if m.PollId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVotePollBasicResponse) 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 *MsgVotePollBasicResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVotePollBasicResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Sig) > 0 { + i -= len(m.Sig) + copy(dAtA[i:], m.Sig) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sig))) + i-- + dAtA[i] = 0x32 + } + if m.PubKey != nil { + { + size, err := m.PubKey.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTx(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Expiry.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size, err := m.Options.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.PollId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgVotePollAgg) 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 *MsgVotePollAgg) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVotePollAgg) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTx(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x32 + } + if len(m.AggSig) > 0 { + i -= len(m.AggSig) + copy(dAtA[i:], m.AggSig) + i = encodeVarintTx(dAtA, i, uint64(len(m.AggSig))) + i-- + dAtA[i] = 0x2a + } + { + size, err := m.Expiry.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Votes) > 0 { + for iNdEx := len(m.Votes) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Votes[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.PollId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgVotePollAggResponse) 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 *MsgVotePollAggResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgVotePollAggResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgCreateGroup) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Members) > 0 { + for _, e := range m.Members { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.BlsOnly { + n += 2 + } + return n +} + +func (m *MsgCreateGroupResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovTx(uint64(m.GroupId)) + } + return n +} + +func (m *MsgUpdateGroupMembers) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.GroupId != 0 { + n += 1 + sovTx(uint64(m.GroupId)) + } + if len(m.MemberUpdates) > 0 { + for _, e := range m.MemberUpdates { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgUpdateGroupMembersResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateGroupAdmin) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.GroupId != 0 { + n += 1 + sovTx(uint64(m.GroupId)) + } + l = len(m.NewAdmin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateGroupAdminResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateGroupMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.GroupId != 0 { + n += 1 + sovTx(uint64(m.GroupId)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateGroupMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgCreateGroupAccount) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.GroupId != 0 { + n += 1 + sovTx(uint64(m.GroupId)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.DecisionPolicy != nil { + l = m.DecisionPolicy.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgCreateGroupAccountResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateGroupAccountAdmin) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.NewAdmin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateGroupAccountAdminResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateGroupAccountDecisionPolicy) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.DecisionPolicy != nil { + l = m.DecisionPolicy.Size() + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgUpdateGroupAccountMetadata) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgUpdateGroupAccountMetadataResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgCreateProposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Proposers) > 0 { + for _, s := range m.Proposers { + l = len(s) + n += 1 + l + sovTx(uint64(l)) + } + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if len(m.Msgs) > 0 { + for _, e := range m.Msgs { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + if m.Exec != 0 { + n += 1 + sovTx(uint64(m.Exec)) + } + return n +} + +func (m *MsgCreateProposalResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + return n +} + +func (m *MsgVote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Choice != 0 { + n += 1 + sovTx(uint64(m.Choice)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Exec != 0 { + n += 1 + sovTx(uint64(m.Exec)) + } + return n +} + +func (m *MsgVoteResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgVoteBasic) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + if m.Choice != 0 { + n += 1 + sovTx(uint64(m.Choice)) + } + l = m.Expiry.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgVoteBasicResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + if m.Choice != 0 { + n += 1 + sovTx(uint64(m.Choice)) + } + l = m.Expiry.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PubKey != nil { + l = m.PubKey.Size() + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Sig) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgVoteAgg) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + if len(m.Votes) > 0 { + l = 0 + for _, e := range m.Votes { + l += sovTx(uint64(e)) + } + n += 1 + sovTx(uint64(l)) + l + } + l = m.Expiry.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.AggSig) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.Exec != 0 { + n += 1 + sovTx(uint64(m.Exec)) + } + return n +} + +func (m *MsgVoteAggResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgExec) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTx(uint64(m.ProposalId)) + } + l = len(m.Signer) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgExecResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgCreatePoll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovTx(uint64(m.GroupId)) + } + l = len(m.Title) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Options.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.VoteLimit != 0 { + n += 1 + sovTx(uint64(m.VoteLimit)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Timeout.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgCreatePollResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovTx(uint64(m.PollId)) + } + return n +} + +func (m *MsgVotePoll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovTx(uint64(m.PollId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Options.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgVotePollResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func (m *MsgVotePollBasic) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovTx(uint64(m.PollId)) + } + l = len(m.Option) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = m.Expiry.Size() + n += 1 + l + sovTx(uint64(l)) + return n +} + +func (m *MsgVotePollBasicResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovTx(uint64(m.PollId)) + } + l = m.Options.Size() + n += 1 + l + sovTx(uint64(l)) + l = m.Expiry.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PubKey != nil { + l = m.PubKey.Size() + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Sig) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgVotePollAgg) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PollId != 0 { + n += 1 + sovTx(uint64(m.PollId)) + } + if len(m.Votes) > 0 { + for _, e := range m.Votes { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + l = m.Expiry.Size() + n += 1 + l + sovTx(uint64(l)) + l = len(m.AggSig) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgVotePollAggResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgCreateGroup) 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: MsgCreateGroup: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateGroup: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, Member{}) + if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlsOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.BlsOnly = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateGroupResponse) 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: MsgCreateGroupResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateGroupResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupMembers) 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: MsgUpdateGroupMembers: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupMembers: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MemberUpdates", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.MemberUpdates = append(m.MemberUpdates, Member{}) + if err := m.MemberUpdates[len(m.MemberUpdates)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupMembersResponse) 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: MsgUpdateGroupMembersResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupMembersResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAdmin) 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: MsgUpdateGroupAdmin: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAdmin: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewAdmin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NewAdmin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAdminResponse) 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: MsgUpdateGroupAdminResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAdminResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupMetadata) 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: MsgUpdateGroupMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupMetadataResponse) 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: MsgUpdateGroupMetadataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateGroupAccount) 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: MsgCreateGroupAccount: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateGroupAccount: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DecisionPolicy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DecisionPolicy == nil { + m.DecisionPolicy = &types.Any{} + } + if err := m.DecisionPolicy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateGroupAccountResponse) 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: MsgCreateGroupAccountResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateGroupAccountResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAccountAdmin) 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: MsgUpdateGroupAccountAdmin: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAccountAdmin: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NewAdmin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NewAdmin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAccountAdminResponse) 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: MsgUpdateGroupAccountAdminResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAccountAdminResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAccountDecisionPolicy) 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: MsgUpdateGroupAccountDecisionPolicy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAccountDecisionPolicy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DecisionPolicy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DecisionPolicy == nil { + m.DecisionPolicy = &types.Any{} + } + if err := m.DecisionPolicy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAccountDecisionPolicyResponse) 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: MsgUpdateGroupAccountDecisionPolicyResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAccountDecisionPolicyResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAccountMetadata) 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: MsgUpdateGroupAccountMetadata: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAccountMetadata: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateGroupAccountMetadataResponse) 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: MsgUpdateGroupAccountMetadataResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateGroupAccountMetadataResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateProposal) 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: MsgCreateProposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateProposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposers", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposers = append(m.Proposers, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msgs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Msgs = append(m.Msgs, &types.Any{}) + if err := m.Msgs[len(m.Msgs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Exec", wireType) + } + m.Exec = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Exec |= Exec(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateProposalResponse) 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: MsgCreateProposalResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateProposalResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVote) 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: MsgVote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Choice", wireType) + } + m.Choice = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Choice |= Choice(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Exec", wireType) + } + m.Exec = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Exec |= Exec(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteResponse) 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: MsgVoteResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteBasic) 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: MsgVoteBasic: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteBasic: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Choice", wireType) + } + m.Choice = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Choice |= Choice(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteBasicResponse) 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: MsgVoteBasicResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteBasicResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Choice", wireType) + } + m.Choice = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Choice |= Choice(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PubKey == nil { + m.PubKey = &types.Any{} + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sig", 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.Sig = append(m.Sig[:0], dAtA[iNdEx:postIndex]...) + if m.Sig == nil { + m.Sig = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteAgg) 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: MsgVoteAgg: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteAgg: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType == 0 { + var v Choice + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= Choice(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Votes = append(m.Votes, v) + } else if wireType == 2 { + var packedLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + packedLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if packedLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + packedLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + var elementCount int + if elementCount != 0 && len(m.Votes) == 0 { + m.Votes = make([]Choice, 0, elementCount) + } + for iNdEx < postIndex { + var v Choice + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= Choice(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Votes = append(m.Votes, v) + } + } else { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggSig", 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.AggSig = append(m.AggSig[:0], dAtA[iNdEx:postIndex]...) + if m.AggSig == nil { + m.AggSig = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Exec", wireType) + } + m.Exec = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Exec |= Exec(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVoteAggResponse) 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: MsgVoteAggResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVoteAggResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgExec) 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: MsgExec: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgExec: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Signer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Signer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgExecResponse) 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: MsgExecResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgExecResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreatePoll) 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: MsgCreatePoll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreatePoll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteLimit", wireType) + } + m.VoteLimit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteLimit |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timeout", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Timeout.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreatePollResponse) 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: MsgCreatePollResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreatePollResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVotePoll) 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: MsgVotePoll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVotePoll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVotePollResponse) 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: MsgVotePollResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVotePollResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVotePollBasic) 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: MsgVotePollBasic: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVotePollBasic: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Option", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Option = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVotePollBasicResponse) 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: MsgVotePollBasicResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVotePollBasicResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PubKey", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.PubKey == nil { + m.PubKey = &types.Any{} + } + if err := m.PubKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sig", 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.Sig = append(m.Sig[:0], dAtA[iNdEx:postIndex]...) + if m.Sig == nil { + m.Sig = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVotePollAgg) 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: MsgVotePollAgg: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVotePollAgg: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Votes", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Votes = append(m.Votes, Options{}) + if err := m.Votes[len(m.Votes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Expiry", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Expiry.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AggSig", 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.AggSig = append(m.AggSig[:0], dAtA[iNdEx:postIndex]...) + if m.AggSig == nil { + m.AggSig = []byte{} + } + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", 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.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgVotePollAggResponse) 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: MsgVotePollAggResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgVotePollAggResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (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 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/group/types.go b/x/group/types.go new file mode 100644 index 0000000000..1160a041e2 --- /dev/null +++ b/x/group/types.go @@ -0,0 +1,616 @@ +package group + +import ( + "fmt" + "time" + + "github.com/cockroachdb/apd/v2" + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/types/math" + proto "github.com/gogo/protobuf/proto" + "github.com/gogo/protobuf/types" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +type ID uint64 + +func (g ID) Uint64() uint64 { + return uint64(g) +} + +func (g ID) Empty() bool { + return g == 0 +} + +func (g ID) Bytes() []byte { + return orm.EncodeSequence(uint64(g)) +} + +type ProposalID uint64 + +func (p ProposalID) Bytes() []byte { + return orm.EncodeSequence(uint64(p)) +} + +func (p ProposalID) Uint64() uint64 { + return uint64(p) +} +func (p ProposalID) Empty() bool { + return p == 0 +} + +type DecisionPolicyResult struct { + Allow bool + Final bool +} + +// DecisionPolicy is the persistent set of rules to determine the result of election on a proposal. +type DecisionPolicy interface { + codec.ProtoMarshaler + + orm.Validateable + GetTimeout() types.Duration + Allow(tally Tally, totalPower string, votingDuration time.Duration) (DecisionPolicyResult, error) + Validate(g GroupInfo) error +} + +// Implements DecisionPolicy Interface +var _ DecisionPolicy = &ThresholdDecisionPolicy{} + +// NewThresholdDecisionPolicy creates a threshold DecisionPolicy +func NewThresholdDecisionPolicy(threshold string, timeout types.Duration) DecisionPolicy { + return &ThresholdDecisionPolicy{threshold, timeout} +} + +// Allow allows a proposal to pass when the tally of yes votes equals or exceeds the threshold before the timeout. +func (p ThresholdDecisionPolicy) Allow(tally Tally, totalPower string, votingDuration time.Duration) (DecisionPolicyResult, error) { + timeout, err := types.DurationFromProto(&p.Timeout) + if err != nil { + return DecisionPolicyResult{}, err + } + if timeout <= votingDuration { + return DecisionPolicyResult{Allow: false, Final: true}, nil + } + + threshold, err := math.ParsePositiveDecimal(p.Threshold) + if err != nil { + return DecisionPolicyResult{}, err + } + yesCount, err := math.ParseNonNegativeDecimal(tally.YesCount) + if err != nil { + return DecisionPolicyResult{}, err + } + if yesCount.Cmp(threshold) >= 0 { + return DecisionPolicyResult{Allow: true, Final: true}, nil + } + + totalPowerDec, err := math.ParseNonNegativeDecimal(totalPower) + if err != nil { + return DecisionPolicyResult{}, err + } + totalCounts, err := tally.TotalCounts() + if err != nil { + return DecisionPolicyResult{}, err + } + var undecided apd.Decimal + err = math.SafeSub(&undecided, totalPowerDec, totalCounts) + if err != nil { + return DecisionPolicyResult{}, err + } + var sum apd.Decimal + err = math.Add(&sum, yesCount, &undecided) + if err != nil { + return DecisionPolicyResult{}, err + } + if sum.Cmp(threshold) < 0 { + return DecisionPolicyResult{Allow: false, Final: true}, nil + } + return DecisionPolicyResult{Allow: false, Final: false}, nil +} + +// Validate returns an error if policy threshold is greater than the total group weight +func (p *ThresholdDecisionPolicy) Validate(g GroupInfo) error { + threshold, err := math.ParsePositiveDecimal(p.Threshold) + if err != nil { + return sdkerrors.Wrap(err, "threshold") + } + totalWeight, err := math.ParseNonNegativeDecimal(g.TotalWeight) + if err != nil { + return sdkerrors.Wrap(err, "group total weight") + } + if threshold.Cmp(totalWeight) > 0 { + return sdkerrors.Wrap(ErrInvalid, "policy threshold should not be greater than the total group weight") + } + return nil +} + +func (p ThresholdDecisionPolicy) ValidateBasic() error { + if _, err := math.ParsePositiveDecimal(p.Threshold); err != nil { + return sdkerrors.Wrap(err, "threshold") + } + + timeout, err := types.DurationFromProto(&p.Timeout) + if err != nil { + return sdkerrors.Wrap(err, "timeout") + } + + if timeout <= time.Nanosecond { + return sdkerrors.Wrap(ErrInvalid, "timeout") + } + return nil +} + +func (g GroupMember) PrimaryKeyFields() []interface{} { + return []interface{}{ID(g.GroupId).Bytes(), g.Member.Address} +} + +func (g GroupAccountInfo) PrimaryKeyFields() []interface{} { + addr, err := sdk.AccAddressFromBech32(g.Address) + if err != nil { + panic(err) + } + return []interface{}{[]byte(addr)} +} + +var _ orm.Validateable = GroupAccountInfo{} + +// NewGroupAccountInfo creates a new GroupAccountInfo instance +func NewGroupAccountInfo(address sdk.AccAddress, group uint64, admin sdk.AccAddress, metadata []byte, + version uint64, decisionPolicy DecisionPolicy, derivationKey []byte) (GroupAccountInfo, error) { + p := GroupAccountInfo{ + Address: address.String(), + GroupId: group, + Admin: admin.String(), + Metadata: metadata, + Version: version, + DerivationKey: derivationKey, + } + + err := p.SetDecisionPolicy(decisionPolicy) + if err != nil { + return GroupAccountInfo{}, err + } + + return p, nil +} + +func (g *GroupAccountInfo) SetDecisionPolicy(decisionPolicy DecisionPolicy) error { + msg, ok := decisionPolicy.(proto.Message) + if !ok { + return fmt.Errorf("can't proto marshal %T", msg) + } + any, err := codectypes.NewAnyWithValue(msg) + if err != nil { + return err + } + g.DecisionPolicy = any + return nil +} + +func (g GroupAccountInfo) GetDecisionPolicy() DecisionPolicy { + decisionPolicy, ok := g.DecisionPolicy.GetCachedValue().(DecisionPolicy) + if !ok { + return nil + } + return decisionPolicy +} + +func (g GroupAccountInfo) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(g.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + _, err = sdk.AccAddressFromBech32(g.Address) + if err != nil { + return sdkerrors.Wrap(err, "group account") + } + + if g.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + } + if g.Version == 0 { + return sdkerrors.Wrap(ErrEmpty, "version") + } + policy := g.GetDecisionPolicy() + + if policy == nil { + return sdkerrors.Wrap(ErrEmpty, "policy") + } + if err := policy.ValidateBasic(); err != nil { + return sdkerrors.Wrap(err, "policy") + } + + if g.DerivationKey == nil { + return sdkerrors.Wrap(ErrEmpty, "derivationKey") + } + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (g GroupAccountInfo) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + var decisionPolicy DecisionPolicy + return unpacker.UnpackAny(g.DecisionPolicy, &decisionPolicy) +} + +func (v Vote) PrimaryKeyFields() []interface{} { + return []interface{}{v.ProposalId, v.Voter} +} + +var _ orm.Validateable = Vote{} + +func (v Vote) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(v.Voter) + if err != nil { + return sdkerrors.Wrap(err, "voter") + } + + if v.ProposalId == 0 { + return sdkerrors.Wrap(ErrEmpty, "proposal") + } + if v.Choice == Choice_CHOICE_UNSPECIFIED { + return sdkerrors.Wrap(ErrEmpty, "choice") + } + if _, ok := Choice_name[int32(v.Choice)]; !ok { + return sdkerrors.Wrap(ErrInvalid, "choice") + } + t, err := types.TimestampFromProto(&v.SubmittedAt) + if err != nil { + return sdkerrors.Wrap(err, "submitted at") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "submitted at") + } + return nil +} + +// ChoiceFromString returns a Choice from a string. It returns an error +// if the string is invalid. +func ChoiceFromString(str string) (Choice, error) { + choice, ok := Choice_value[str] + if !ok { + return Choice_CHOICE_UNSPECIFIED, fmt.Errorf("'%s' is not a valid vote choice", str) + } + return Choice(choice), nil +} + +// MaxMetadataLength defines the max length of the metadata bytes field +// for various entities within the group module +// TODO: This could be used as params once x/params is upgraded to use protobuf +const MaxMetadataLength = 255 +const MaxTitleLength = 255 +const MaxOptionLength = 127 + +// assertMetadataLength returns an error if given metadata length +// is greater than a fixed maxMetadataLength. +func assertMetadataLength(metadata []byte, description string) error { + if len(metadata) > MaxMetadataLength { + return sdkerrors.Wrap(ErrMaxLimit, description) + } + return nil +} + +// assertTitleLength returns an error if given title length +// is greater than a fixed maxTitleLength. +func assertTitleLength(title string, description string) error { + if len(title) > MaxTitleLength { + return sdkerrors.Wrap(ErrMaxLimit, description) + } + return nil +} + +// assertOptionsLength returns an error if the length of options +// is greater than a fixed maxOptionLength or the lenght of any option is greater than a fixed MaxTitleLength. +func assertOptionsLength(options Options, description string) error { + if len(options.Titles) > MaxOptionLength { + return sdkerrors.Wrapf(ErrMaxLimit, "%s: %s", description, "number of option titles") + } + for _, t := range options.Titles { + if len(t) > MaxTitleLength { + return sdkerrors.Wrapf(ErrMaxLimit, "%s: %s", description, "option title length") + } + } + return nil +} + +var _ orm.Validateable = GroupInfo{} + +func (g GroupInfo) ValidateBasic() error { + if g.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + } + + _, err := sdk.AccAddressFromBech32(g.Admin) + if err != nil { + return sdkerrors.Wrap(err, "admin") + } + + if _, err := math.ParseNonNegativeDecimal(g.TotalWeight); err != nil { + return sdkerrors.Wrap(err, "total weight") + } + if g.Version == 0 { + return sdkerrors.Wrap(ErrEmpty, "version") + } + return nil +} + +func (g GroupInfo) PrimaryKeyFields() []interface{} { + return []interface{}{g.GroupId} +} + +var _ orm.Validateable = GroupMember{} + +func (g GroupMember) ValidateBasic() error { + if g.GroupId == 0 { + return sdkerrors.Wrap(ErrEmpty, "group") + } + + err := g.Member.ValidateBasic() + if err != nil { + return sdkerrors.Wrap(err, "member") + } + return nil +} + +func (v VotePoll) PrimaryKeyFields() []interface{} { + return []interface{}{v.PollId, v.Voter} +} + +var _ orm.Validateable = VotePoll{} + +func (v VotePoll) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(v.Voter) + if err != nil { + return sdkerrors.Wrap(err, "voter") + } + + if v.PollId == 0 { + return sdkerrors.Wrap(ErrEmpty, "poll") + } + + if err := assertMetadataLength(v.Metadata, "metadata"); err != nil { + return err + } + + if err := assertOptionsLength(v.Options, "vote options"); err != nil { + return err + } + + if err := v.Options.ValidateBasic(); err != nil { + return err + } + + t, err := types.TimestampFromProto(&v.SubmittedAt) + if err != nil { + return sdkerrors.Wrap(err, "submitted at") + } + if t.IsZero() { + return sdkerrors.Wrap(ErrEmpty, "submitted at") + } + + return nil +} + +func (t *Tally) Sub(vote Vote, weight string) error { + if err := t.operation(vote, weight, math.SafeSub); err != nil { + return err + } + return nil +} + +func (t *Tally) Add(vote Vote, weight string) error { + if err := t.operation(vote, weight, math.Add); err != nil { + return err + } + return nil +} + +type operation func(res, x, y *apd.Decimal) error + +func (t *Tally) operation(vote Vote, weight string, op operation) error { + weightDec, err := math.ParsePositiveDecimal(weight) + if err != nil { + return err + } + + yesCount, err := t.GetYesCount() + if err != nil { + return sdkerrors.Wrap(err, "yes count") + } + noCount, err := t.GetNoCount() + if err != nil { + return sdkerrors.Wrap(err, "no count") + } + abstainCount, err := t.GetAbstainCount() + if err != nil { + return sdkerrors.Wrap(err, "abstain count") + } + vetoCount, err := t.GetVetoCount() + if err != nil { + return sdkerrors.Wrap(err, "veto count") + } + + switch vote.Choice { + case Choice_CHOICE_YES: + err := op(yesCount, yesCount, weightDec) + if err != nil { + return sdkerrors.Wrap(err, "yes count") + } + t.YesCount = math.DecimalString(yesCount) + case Choice_CHOICE_NO: + err := op(noCount, noCount, weightDec) + if err != nil { + return sdkerrors.Wrap(err, "no count") + } + t.NoCount = math.DecimalString(noCount) + case Choice_CHOICE_ABSTAIN: + err := op(abstainCount, abstainCount, weightDec) + if err != nil { + return sdkerrors.Wrap(err, "abstain count") + } + t.AbstainCount = math.DecimalString(abstainCount) + case Choice_CHOICE_VETO: + err := op(vetoCount, vetoCount, weightDec) + if err != nil { + return sdkerrors.Wrap(err, "veto count") + } + t.VetoCount = math.DecimalString(vetoCount) + default: + return sdkerrors.Wrapf(ErrInvalid, "unknown choice %s", vote.Choice.String()) + } + return nil +} + +// TotalCounts is the sum of all weights. +func (t Tally) TotalCounts() (*apd.Decimal, error) { + yesCount, err := t.GetYesCount() + if err != nil { + return nil, sdkerrors.Wrap(err, "yes count") + } + noCount, err := t.GetNoCount() + if err != nil { + return nil, sdkerrors.Wrap(err, "no count") + } + abstainCount, err := t.GetAbstainCount() + if err != nil { + return nil, sdkerrors.Wrap(err, "abstain count") + } + vetoCount, err := t.GetVetoCount() + if err != nil { + return nil, sdkerrors.Wrap(err, "veto count") + } + + totalCounts := apd.New(0, 0) + err = math.Add(totalCounts, totalCounts, yesCount) + if err != nil { + return nil, err + } + err = math.Add(totalCounts, totalCounts, noCount) + if err != nil { + return nil, err + } + err = math.Add(totalCounts, totalCounts, abstainCount) + if err != nil { + return nil, err + } + err = math.Add(totalCounts, totalCounts, vetoCount) + if err != nil { + return nil, err + } + return totalCounts, nil +} + +func (t Tally) GetYesCount() (*apd.Decimal, error) { + yesCount, err := math.ParseNonNegativeDecimal(t.YesCount) + if err != nil { + return nil, err + } + return yesCount, nil +} + +func (t Tally) GetNoCount() (*apd.Decimal, error) { + noCount, err := math.ParseNonNegativeDecimal(t.NoCount) + if err != nil { + return nil, err + } + return noCount, nil +} + +func (t Tally) GetAbstainCount() (*apd.Decimal, error) { + abstainCount, err := math.ParseNonNegativeDecimal(t.AbstainCount) + if err != nil { + return nil, err + } + return abstainCount, nil +} + +func (t Tally) GetVetoCount() (*apd.Decimal, error) { + vetoCount, err := math.ParseNonNegativeDecimal(t.VetoCount) + if err != nil { + return nil, err + } + return vetoCount, nil +} + +func (t Tally) ValidateBasic() error { + if _, err := t.GetYesCount(); err != nil { + return sdkerrors.Wrap(err, "yes count") + } + if _, err := t.GetNoCount(); err != nil { + return sdkerrors.Wrap(err, "no count") + } + if _, err := t.GetAbstainCount(); err != nil { + return sdkerrors.Wrap(err, "abstain count") + } + if _, err := t.GetVetoCount(); err != nil { + return sdkerrors.Wrap(err, "veto count") + } + return nil +} + +func (t *TallyPoll) Sub(vote VotePoll, weight string) error { + if err := t.operation(vote, weight, math.SafeSub); err != nil { + return err + } + return nil +} + +func (t *TallyPoll) Add(vote VotePoll, weight string) error { + if err := t.operation(vote, weight, math.Add); err != nil { + return err + } + return nil +} + +func (t *TallyPoll) operation(vote VotePoll, weight string, op operation) error { + weightDec, err := math.ParsePositiveDecimal(weight) + if err != nil { + return err + } + + for _, option := range vote.Options.Titles { + res, err := math.ParseNonNegativeDecimal("0") + if err != nil { + return err + } + if x, ok := t.Counts[option]; ok { + res, err = math.ParseNonNegativeDecimal(x) + if err != nil { + return err + } + } + err = op(res, res, weightDec) + if err != nil { + return sdkerrors.Wrap(err, "count") + } + + t.Counts[option] = math.DecimalString(res) + } + + return nil +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (q QueryGroupAccountsByGroupResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpackGroupAccounts(unpacker, q.GroupAccounts) +} + +// UnpackInterfaces implements UnpackInterfacesMessage.UnpackInterfaces +func (q QueryGroupAccountsByAdminResponse) UnpackInterfaces(unpacker codectypes.AnyUnpacker) error { + return unpackGroupAccounts(unpacker, q.GroupAccounts) +} + +func unpackGroupAccounts(unpacker codectypes.AnyUnpacker, accs []*GroupAccountInfo) error { + for _, g := range accs { + err := g.UnpackInterfaces(unpacker) + if err != nil { + return err + } + } + + return nil +} diff --git a/x/group/types.pb.go b/x/group/types.pb.go new file mode 100644 index 0000000000..2b60aef509 --- /dev/null +++ b/x/group/types.pb.go @@ -0,0 +1,4888 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: regen/group/v1alpha1/types.proto + +package group + +import ( + bytes "bytes" + fmt "fmt" + types1 "github.com/cosmos/cosmos-sdk/codec/types" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + types "github.com/gogo/protobuf/types" + _ "github.com/regen-network/cosmos-proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Choice defines available types of choices for voting. +type Choice int32 + +const ( + // CHOICE_UNSPECIFIED defines a no-op voting choice. + Choice_CHOICE_UNSPECIFIED Choice = 0 + // CHOICE_NO defines a no voting choice. + Choice_CHOICE_NO Choice = 1 + // CHOICE_YES defines a yes voting choice. + Choice_CHOICE_YES Choice = 2 + // CHOICE_ABSTAIN defines an abstaining voting choice. + Choice_CHOICE_ABSTAIN Choice = 3 + // CHOICE_VETO defines a voting choice with veto. + Choice_CHOICE_VETO Choice = 4 +) + +var Choice_name = map[int32]string{ + 0: "CHOICE_UNSPECIFIED", + 1: "CHOICE_NO", + 2: "CHOICE_YES", + 3: "CHOICE_ABSTAIN", + 4: "CHOICE_VETO", +} + +var Choice_value = map[string]int32{ + "CHOICE_UNSPECIFIED": 0, + "CHOICE_NO": 1, + "CHOICE_YES": 2, + "CHOICE_ABSTAIN": 3, + "CHOICE_VETO": 4, +} + +func (x Choice) String() string { + return proto.EnumName(Choice_name, int32(x)) +} + +func (Choice) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{0} +} + +// Status defines proposal statuses. +type Proposal_Status int32 + +const ( + // An empty value is invalid and not allowed. + ProposalStatusInvalid Proposal_Status = 0 + // Initial status of a proposal when persisted. + ProposalStatusSubmitted Proposal_Status = 1 + // Final status of a proposal when the final tally was executed. + ProposalStatusClosed Proposal_Status = 2 + // Final status of a proposal when the group was modified before the final tally. + ProposalStatusAborted Proposal_Status = 3 +) + +var Proposal_Status_name = map[int32]string{ + 0: "STATUS_UNSPECIFIED", + 1: "STATUS_SUBMITTED", + 2: "STATUS_CLOSED", + 3: "STATUS_ABORTED", +} + +var Proposal_Status_value = map[string]int32{ + "STATUS_UNSPECIFIED": 0, + "STATUS_SUBMITTED": 1, + "STATUS_CLOSED": 2, + "STATUS_ABORTED": 3, +} + +func (x Proposal_Status) String() string { + return proto.EnumName(Proposal_Status_name, int32(x)) +} + +func (Proposal_Status) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{6, 0} +} + +// Result defines types of proposal results. +type Proposal_Result int32 + +const ( + // An empty value is invalid and not allowed + ProposalResultInvalid Proposal_Result = 0 + // Until a final tally has happened the status is unfinalized + ProposalResultUnfinalized Proposal_Result = 1 + // Final result of the tally + ProposalResultAccepted Proposal_Result = 2 + // Final result of the tally + ProposalResultRejected Proposal_Result = 3 +) + +var Proposal_Result_name = map[int32]string{ + 0: "RESULT_UNSPECIFIED", + 1: "RESULT_UNFINALIZED", + 2: "RESULT_ACCEPTED", + 3: "RESULT_REJECTED", +} + +var Proposal_Result_value = map[string]int32{ + "RESULT_UNSPECIFIED": 0, + "RESULT_UNFINALIZED": 1, + "RESULT_ACCEPTED": 2, + "RESULT_REJECTED": 3, +} + +func (x Proposal_Result) String() string { + return proto.EnumName(Proposal_Result_name, int32(x)) +} + +func (Proposal_Result) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{6, 1} +} + +// ExecutorResult defines types of proposal executor results. +type Proposal_ExecutorResult int32 + +const ( + // An empty value is not allowed. + ProposalExecutorResultInvalid Proposal_ExecutorResult = 0 + // We have not yet run the executor. + ProposalExecutorResultNotRun Proposal_ExecutorResult = 1 + // The executor was successful and proposed action updated state. + ProposalExecutorResultSuccess Proposal_ExecutorResult = 2 + // The executor returned an error and proposed action didn't update state. + ProposalExecutorResultFailure Proposal_ExecutorResult = 3 +) + +var Proposal_ExecutorResult_name = map[int32]string{ + 0: "EXECUTOR_RESULT_UNSPECIFIED", + 1: "EXECUTOR_RESULT_NOT_RUN", + 2: "EXECUTOR_RESULT_SUCCESS", + 3: "EXECUTOR_RESULT_FAILURE", +} + +var Proposal_ExecutorResult_value = map[string]int32{ + "EXECUTOR_RESULT_UNSPECIFIED": 0, + "EXECUTOR_RESULT_NOT_RUN": 1, + "EXECUTOR_RESULT_SUCCESS": 2, + "EXECUTOR_RESULT_FAILURE": 3, +} + +func (x Proposal_ExecutorResult) String() string { + return proto.EnumName(Proposal_ExecutorResult_name, int32(x)) +} + +func (Proposal_ExecutorResult) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{6, 2} +} + +// Status defines poll statuses. +type Poll_Status int32 + +const ( + // An empty value is invalid and not allowed. + PollStatusInvalid Poll_Status = 0 + // Initial status of a poll when persisted. + PollStatusSubmitted Poll_Status = 1 + // Final status of a poll when the final tally was executed. + PollStatusClosed Poll_Status = 2 + // Final status of a poll when the group was modified before the final tally. + PollStatusAborted Poll_Status = 3 +) + +var Poll_Status_name = map[int32]string{ + 0: "STATUS_UNSPECIFIED", + 1: "STATUS_SUBMITTED", + 2: "STATUS_CLOSED", + 3: "STATUS_ABORTED", +} + +var Poll_Status_value = map[string]int32{ + "STATUS_UNSPECIFIED": 0, + "STATUS_SUBMITTED": 1, + "STATUS_CLOSED": 2, + "STATUS_ABORTED": 3, +} + +func (x Poll_Status) String() string { + return proto.EnumName(Poll_Status_name, int32(x)) +} + +func (Poll_Status) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{11, 0} +} + +// Member represents a group member with an account address, +// non-zero weight and metadata. +type Member struct { + // address is the member's account address. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // weight is the member's voting weight that should be greater than 0. + Weight string `protobuf:"bytes,2,opt,name=weight,proto3" json:"weight,omitempty"` + // metadata is any arbitrary metadata to attached to the member. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` +} + +func (m *Member) Reset() { *m = Member{} } +func (m *Member) String() string { return proto.CompactTextString(m) } +func (*Member) ProtoMessage() {} +func (*Member) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{0} +} +func (m *Member) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Member) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Member.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 *Member) XXX_Merge(src proto.Message) { + xxx_messageInfo_Member.Merge(m, src) +} +func (m *Member) XXX_Size() int { + return m.Size() +} +func (m *Member) XXX_DiscardUnknown() { + xxx_messageInfo_Member.DiscardUnknown(m) +} + +var xxx_messageInfo_Member proto.InternalMessageInfo + +func (m *Member) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *Member) GetWeight() string { + if m != nil { + return m.Weight + } + return "" +} + +func (m *Member) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +// Members defines a repeated slice of Member objects. +type Members struct { + // members is the list of members. + Members []Member `protobuf:"bytes,1,rep,name=members,proto3" json:"members"` +} + +func (m *Members) Reset() { *m = Members{} } +func (m *Members) String() string { return proto.CompactTextString(m) } +func (*Members) ProtoMessage() {} +func (*Members) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{1} +} +func (m *Members) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Members) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Members.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 *Members) XXX_Merge(src proto.Message) { + xxx_messageInfo_Members.Merge(m, src) +} +func (m *Members) XXX_Size() int { + return m.Size() +} +func (m *Members) XXX_DiscardUnknown() { + xxx_messageInfo_Members.DiscardUnknown(m) +} + +var xxx_messageInfo_Members proto.InternalMessageInfo + +func (m *Members) GetMembers() []Member { + if m != nil { + return m.Members + } + return nil +} + +// ThresholdDecisionPolicy implements the DecisionPolicy interface +type ThresholdDecisionPolicy struct { + // threshold is the minimum weighted sum of yes votes that must be met or exceeded for a proposal to succeed. + Threshold string `protobuf:"bytes,1,opt,name=threshold,proto3" json:"threshold,omitempty"` + // timeout is the duration from submission of a proposal to the end of voting period + // Within this times votes and exec messages can be submitted. + Timeout types.Duration `protobuf:"bytes,2,opt,name=timeout,proto3" json:"timeout"` +} + +func (m *ThresholdDecisionPolicy) Reset() { *m = ThresholdDecisionPolicy{} } +func (m *ThresholdDecisionPolicy) String() string { return proto.CompactTextString(m) } +func (*ThresholdDecisionPolicy) ProtoMessage() {} +func (*ThresholdDecisionPolicy) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{2} +} +func (m *ThresholdDecisionPolicy) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ThresholdDecisionPolicy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ThresholdDecisionPolicy.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 *ThresholdDecisionPolicy) XXX_Merge(src proto.Message) { + xxx_messageInfo_ThresholdDecisionPolicy.Merge(m, src) +} +func (m *ThresholdDecisionPolicy) XXX_Size() int { + return m.Size() +} +func (m *ThresholdDecisionPolicy) XXX_DiscardUnknown() { + xxx_messageInfo_ThresholdDecisionPolicy.DiscardUnknown(m) +} + +var xxx_messageInfo_ThresholdDecisionPolicy proto.InternalMessageInfo + +func (m *ThresholdDecisionPolicy) GetThreshold() string { + if m != nil { + return m.Threshold + } + return "" +} + +func (m *ThresholdDecisionPolicy) GetTimeout() types.Duration { + if m != nil { + return m.Timeout + } + return types.Duration{} +} + +// GroupInfo represents the high-level on-chain information for a group. +type GroupInfo struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // admin is the account address of the group's admin. + Admin string `protobuf:"bytes,2,opt,name=admin,proto3" json:"admin,omitempty"` + // metadata is any arbitrary metadata to attached to the group. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` + // version is used to track changes to a group's membership structure that + // would break existing proposals. Whenever any members weight is changed, + // or any member is added or removed this version is incremented and will + // cause proposals based on older versions of this group to fail + Version uint64 `protobuf:"varint,4,opt,name=version,proto3" json:"version,omitempty"` + // total_weight is the sum of the group members' weights. + TotalWeight string `protobuf:"bytes,5,opt,name=total_weight,json=totalWeight,proto3" json:"total_weight,omitempty"` + // bls_only requires all the group members to use bls public keys so their votes can be aggregated together + BlsOnly bool `protobuf:"varint,6,opt,name=bls_only,json=blsOnly,proto3" json:"bls_only,omitempty"` +} + +func (m *GroupInfo) Reset() { *m = GroupInfo{} } +func (m *GroupInfo) String() string { return proto.CompactTextString(m) } +func (*GroupInfo) ProtoMessage() {} +func (*GroupInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{3} +} +func (m *GroupInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GroupInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GroupInfo.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 *GroupInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_GroupInfo.Merge(m, src) +} +func (m *GroupInfo) XXX_Size() int { + return m.Size() +} +func (m *GroupInfo) XXX_DiscardUnknown() { + xxx_messageInfo_GroupInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_GroupInfo proto.InternalMessageInfo + +func (m *GroupInfo) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *GroupInfo) GetAdmin() string { + if m != nil { + return m.Admin + } + return "" +} + +func (m *GroupInfo) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *GroupInfo) GetVersion() uint64 { + if m != nil { + return m.Version + } + return 0 +} + +func (m *GroupInfo) GetTotalWeight() string { + if m != nil { + return m.TotalWeight + } + return "" +} + +func (m *GroupInfo) GetBlsOnly() bool { + if m != nil { + return m.BlsOnly + } + return false +} + +// GroupMember represents the relationship between a group and a member. +type GroupMember struct { + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,1,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // member is the member data. + Member *Member `protobuf:"bytes,2,opt,name=member,proto3" json:"member,omitempty"` +} + +func (m *GroupMember) Reset() { *m = GroupMember{} } +func (m *GroupMember) String() string { return proto.CompactTextString(m) } +func (*GroupMember) ProtoMessage() {} +func (*GroupMember) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{4} +} +func (m *GroupMember) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GroupMember) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GroupMember.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 *GroupMember) XXX_Merge(src proto.Message) { + xxx_messageInfo_GroupMember.Merge(m, src) +} +func (m *GroupMember) XXX_Size() int { + return m.Size() +} +func (m *GroupMember) XXX_DiscardUnknown() { + xxx_messageInfo_GroupMember.DiscardUnknown(m) +} + +var xxx_messageInfo_GroupMember proto.InternalMessageInfo + +func (m *GroupMember) GetGroupId() uint64 { + if m != nil { + return m.GroupId + } + return 0 +} + +func (m *GroupMember) GetMember() *Member { + if m != nil { + return m.Member + } + return nil +} + +// GroupAccountInfo represents the high-level on-chain information for a group account. +type GroupAccountInfo struct { + // address is the group account address. + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // admin is the account address of the group admin. + Admin string `protobuf:"bytes,3,opt,name=admin,proto3" json:"admin,omitempty"` + // metadata is any arbitrary metadata to attached to the group account. + Metadata []byte `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // version is used to track changes to a group's GroupAccountInfo structure that + // would create a different result on a running proposal. + Version uint64 `protobuf:"varint,5,opt,name=version,proto3" json:"version,omitempty"` + // decision_policy specifies the group account's decision policy. + DecisionPolicy *types1.Any `protobuf:"bytes,6,opt,name=decision_policy,json=decisionPolicy,proto3" json:"decision_policy,omitempty"` + // derivation_key is the "derivation" key of the group account, + // which is needed to derive the group root module key and execute proposals. + DerivationKey []byte `protobuf:"bytes,7,opt,name=derivation_key,json=derivationKey,proto3" json:"derivation_key,omitempty"` +} + +func (m *GroupAccountInfo) Reset() { *m = GroupAccountInfo{} } +func (m *GroupAccountInfo) String() string { return proto.CompactTextString(m) } +func (*GroupAccountInfo) ProtoMessage() {} +func (*GroupAccountInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{5} +} +func (m *GroupAccountInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GroupAccountInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GroupAccountInfo.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 *GroupAccountInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_GroupAccountInfo.Merge(m, src) +} +func (m *GroupAccountInfo) XXX_Size() int { + return m.Size() +} +func (m *GroupAccountInfo) XXX_DiscardUnknown() { + xxx_messageInfo_GroupAccountInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_GroupAccountInfo proto.InternalMessageInfo + +// Proposal defines a group proposal. Any member of a group can submit a proposal +// for a group account to decide upon. +// A proposal consists of a set of `sdk.Msg`s that will be executed if the proposal +// passes as well as some optional metadata associated with the proposal. +type Proposal struct { + // proposal_id is the unique id of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // address is the group account address. + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + // metadata is any arbitrary metadata to attached to the proposal. + Metadata []byte `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` + // proposers are the account addresses of the proposers. + Proposers []string `protobuf:"bytes,4,rep,name=proposers,proto3" json:"proposers,omitempty"` + // submitted_at is a timestamp specifying when a proposal was submitted. + SubmittedAt types.Timestamp `protobuf:"bytes,5,opt,name=submitted_at,json=submittedAt,proto3" json:"submitted_at"` + // group_version tracks the version of the group that this proposal corresponds to. + // When group membership is changed, existing proposals from previous group versions will become invalid. + GroupVersion uint64 `protobuf:"varint,6,opt,name=group_version,json=groupVersion,proto3" json:"group_version,omitempty"` + // group_account_version tracks the version of the group account that this proposal corresponds to. + // When a decision policy is changed, existing proposals from previous policy versions will become invalid. + GroupAccountVersion uint64 `protobuf:"varint,7,opt,name=group_account_version,json=groupAccountVersion,proto3" json:"group_account_version,omitempty"` + // Status represents the high level position in the life cycle of the proposal. Initial value is Submitted. + Status Proposal_Status `protobuf:"varint,8,opt,name=status,proto3,enum=regen.group.v1alpha1.Proposal_Status" json:"status,omitempty"` + // result is the final result based on the votes and election rule. Initial value is unfinalized. + // The result is persisted so that clients can always rely on this state and not have to replicate the logic. + Result Proposal_Result `protobuf:"varint,9,opt,name=result,proto3,enum=regen.group.v1alpha1.Proposal_Result" json:"result,omitempty"` + // vote_state contains the sums of all weighted votes for this proposal. + VoteState Tally `protobuf:"bytes,10,opt,name=vote_state,json=voteState,proto3" json:"vote_state"` + // timeout is the timestamp of the block where the proposal execution times out. Header times of the votes and execution messages + // must be before this end time to be included in the election. After the timeout timestamp the proposal can not be + // executed anymore and should be considered pending delete. + Timeout types.Timestamp `protobuf:"bytes,11,opt,name=timeout,proto3" json:"timeout"` + // executor_result is the final result based on the votes and election rule. Initial value is NotRun. + ExecutorResult Proposal_ExecutorResult `protobuf:"varint,12,opt,name=executor_result,json=executorResult,proto3,enum=regen.group.v1alpha1.Proposal_ExecutorResult" json:"executor_result,omitempty"` + // msgs is a list of Msgs that will be executed if the proposal passes. + Msgs []*types1.Any `protobuf:"bytes,13,rep,name=msgs,proto3" json:"msgs,omitempty"` +} + +func (m *Proposal) Reset() { *m = Proposal{} } +func (m *Proposal) String() string { return proto.CompactTextString(m) } +func (*Proposal) ProtoMessage() {} +func (*Proposal) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{6} +} +func (m *Proposal) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Proposal) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Proposal.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 *Proposal) XXX_Merge(src proto.Message) { + xxx_messageInfo_Proposal.Merge(m, src) +} +func (m *Proposal) XXX_Size() int { + return m.Size() +} +func (m *Proposal) XXX_DiscardUnknown() { + xxx_messageInfo_Proposal.DiscardUnknown(m) +} + +var xxx_messageInfo_Proposal proto.InternalMessageInfo + +// Tally represents the sum of weighted votes. +type Tally struct { + // yes_count is the weighted sum of yes votes. + YesCount string `protobuf:"bytes,1,opt,name=yes_count,json=yesCount,proto3" json:"yes_count,omitempty"` + // no_count is the weighted sum of no votes. + NoCount string `protobuf:"bytes,2,opt,name=no_count,json=noCount,proto3" json:"no_count,omitempty"` + // abstain_count is the weighted sum of abstainers + AbstainCount string `protobuf:"bytes,3,opt,name=abstain_count,json=abstainCount,proto3" json:"abstain_count,omitempty"` + // veto_count is the weighted sum of vetoes. + VetoCount string `protobuf:"bytes,4,opt,name=veto_count,json=vetoCount,proto3" json:"veto_count,omitempty"` +} + +func (m *Tally) Reset() { *m = Tally{} } +func (m *Tally) String() string { return proto.CompactTextString(m) } +func (*Tally) ProtoMessage() {} +func (*Tally) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{7} +} +func (m *Tally) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Tally) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Tally.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 *Tally) XXX_Merge(src proto.Message) { + xxx_messageInfo_Tally.Merge(m, src) +} +func (m *Tally) XXX_Size() int { + return m.Size() +} +func (m *Tally) XXX_DiscardUnknown() { + xxx_messageInfo_Tally.DiscardUnknown(m) +} + +var xxx_messageInfo_Tally proto.InternalMessageInfo + +// Vote represents a vote for a proposal. +type Vote struct { + // proposal is the unique ID of the proposal. + ProposalId uint64 `protobuf:"varint,1,opt,name=proposal_id,json=proposalId,proto3" json:"proposal_id,omitempty"` + // voter is the account address of the voter. + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + // choice is the voter's choice on the proposal. + Choice Choice `protobuf:"varint,3,opt,name=choice,proto3,enum=regen.group.v1alpha1.Choice" json:"choice,omitempty"` + // metadata is any arbitrary metadata to attached to the vote. + Metadata []byte `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // submitted_at is the timestamp when the vote was submitted. + SubmittedAt types.Timestamp `protobuf:"bytes,5,opt,name=submitted_at,json=submittedAt,proto3" json:"submitted_at"` +} + +func (m *Vote) Reset() { *m = Vote{} } +func (m *Vote) String() string { return proto.CompactTextString(m) } +func (*Vote) ProtoMessage() {} +func (*Vote) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{8} +} +func (m *Vote) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Vote) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Vote.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 *Vote) XXX_Merge(src proto.Message) { + xxx_messageInfo_Vote.Merge(m, src) +} +func (m *Vote) XXX_Size() int { + return m.Size() +} +func (m *Vote) XXX_DiscardUnknown() { + xxx_messageInfo_Vote.DiscardUnknown(m) +} + +var xxx_messageInfo_Vote proto.InternalMessageInfo + +func (m *Vote) GetProposalId() uint64 { + if m != nil { + return m.ProposalId + } + return 0 +} + +func (m *Vote) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *Vote) GetChoice() Choice { + if m != nil { + return m.Choice + } + return Choice_CHOICE_UNSPECIFIED +} + +func (m *Vote) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *Vote) GetSubmittedAt() types.Timestamp { + if m != nil { + return m.SubmittedAt + } + return types.Timestamp{} +} + +// TallyPoll represents the sum of weighted votes for a poll. +type TallyPoll struct { + Counts map[string]string `protobuf:"bytes,1,rep,name=counts,proto3" json:"counts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (m *TallyPoll) Reset() { *m = TallyPoll{} } +func (m *TallyPoll) String() string { return proto.CompactTextString(m) } +func (*TallyPoll) ProtoMessage() {} +func (*TallyPoll) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{9} +} +func (m *TallyPoll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *TallyPoll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_TallyPoll.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 *TallyPoll) XXX_Merge(src proto.Message) { + xxx_messageInfo_TallyPoll.Merge(m, src) +} +func (m *TallyPoll) XXX_Size() int { + return m.Size() +} +func (m *TallyPoll) XXX_DiscardUnknown() { + xxx_messageInfo_TallyPoll.DiscardUnknown(m) +} + +var xxx_messageInfo_TallyPoll proto.InternalMessageInfo + +// Options represents the choices voters can vote for a poll. +type Options struct { + Titles []string `protobuf:"bytes,1,rep,name=titles,proto3" json:"titles,omitempty"` +} + +func (m *Options) Reset() { *m = Options{} } +func (m *Options) String() string { return proto.CompactTextString(m) } +func (*Options) ProtoMessage() {} +func (*Options) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{10} +} +func (m *Options) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Options.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 *Options) XXX_Merge(src proto.Message) { + xxx_messageInfo_Options.Merge(m, src) +} +func (m *Options) XXX_Size() int { + return m.Size() +} +func (m *Options) XXX_DiscardUnknown() { + xxx_messageInfo_Options.DiscardUnknown(m) +} + +var xxx_messageInfo_Options proto.InternalMessageInfo + +// Poll defines a group poll. Any member of a group can submit a poll +// for a group to decide upon. +// The options in a poll can be customised by the creator. +type Poll struct { + // poll_id is the unique id of the poll. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // group_id is the unique ID of the group. + GroupId uint64 `protobuf:"varint,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + // title is the title of the poll. + Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"` + // options are the choices of the poll. + Options Options `protobuf:"bytes,4,opt,name=options,proto3" json:"options"` + // creator is the account address of the poll creator. + Creator string `protobuf:"bytes,5,opt,name=creator,proto3" json:"creator,omitempty"` + // vote_limit is the maximum number of options each voter can choose. + VoteLimit int32 `protobuf:"varint,6,opt,name=vote_limit,json=voteLimit,proto3" json:"vote_limit,omitempty"` + // vote_state contains the sums of all weighted votes for this poll. + VoteState TallyPoll `protobuf:"bytes,7,opt,name=vote_state,json=voteState,proto3" json:"vote_state"` + // metadata is any arbitrary metadata to attached to the poll. + Metadata []byte `protobuf:"bytes,8,opt,name=metadata,proto3" json:"metadata,omitempty"` + // submitted_at is a timestamp specifying when a poll was submitted. + SubmittedAt types.Timestamp `protobuf:"bytes,9,opt,name=submitted_at,json=submittedAt,proto3" json:"submitted_at"` + // group_version tracks the version of the group that this poll corresponds to. + // When group membership is changed, existing polls from previous group versions will become invalid. + GroupVersion uint64 `protobuf:"varint,10,opt,name=group_version,json=groupVersion,proto3" json:"group_version,omitempty"` + // Status represents the high level position in the life cycle of the poll. Initial value is Submitted. + Status Poll_Status `protobuf:"varint,11,opt,name=status,proto3,enum=regen.group.v1alpha1.Poll_Status" json:"status,omitempty"` + // timeout is the timestamp of the block where the poll times out. Header times of the votes + // must be before this end time to be included in the election. + Timeout types.Timestamp `protobuf:"bytes,12,opt,name=timeout,proto3" json:"timeout"` +} + +func (m *Poll) Reset() { *m = Poll{} } +func (m *Poll) String() string { return proto.CompactTextString(m) } +func (*Poll) ProtoMessage() {} +func (*Poll) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{11} +} +func (m *Poll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Poll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Poll.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 *Poll) XXX_Merge(src proto.Message) { + xxx_messageInfo_Poll.Merge(m, src) +} +func (m *Poll) XXX_Size() int { + return m.Size() +} +func (m *Poll) XXX_DiscardUnknown() { + xxx_messageInfo_Poll.DiscardUnknown(m) +} + +var xxx_messageInfo_Poll proto.InternalMessageInfo + +// VotePoll represents a vote for a poll. +type VotePoll struct { + // poll_id is the unique ID of the pool. + PollId uint64 `protobuf:"varint,1,opt,name=poll_id,json=pollId,proto3" json:"poll_id,omitempty"` + // voter is the account address of the voter. + Voter string `protobuf:"bytes,2,opt,name=voter,proto3" json:"voter,omitempty"` + // options are the voter's choices on the poll. + Options Options `protobuf:"bytes,3,opt,name=options,proto3" json:"options"` + // metadata is any arbitrary metadata to attached to the vote. + Metadata []byte `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // submitted_at is the timestamp when the vote was submitted. + SubmittedAt types.Timestamp `protobuf:"bytes,5,opt,name=submitted_at,json=submittedAt,proto3" json:"submitted_at"` +} + +func (m *VotePoll) Reset() { *m = VotePoll{} } +func (m *VotePoll) String() string { return proto.CompactTextString(m) } +func (*VotePoll) ProtoMessage() {} +func (*VotePoll) Descriptor() ([]byte, []int) { + return fileDescriptor_9b7906b115009838, []int{12} +} +func (m *VotePoll) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *VotePoll) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_VotePoll.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 *VotePoll) XXX_Merge(src proto.Message) { + xxx_messageInfo_VotePoll.Merge(m, src) +} +func (m *VotePoll) XXX_Size() int { + return m.Size() +} +func (m *VotePoll) XXX_DiscardUnknown() { + xxx_messageInfo_VotePoll.DiscardUnknown(m) +} + +var xxx_messageInfo_VotePoll proto.InternalMessageInfo + +func (m *VotePoll) GetPollId() uint64 { + if m != nil { + return m.PollId + } + return 0 +} + +func (m *VotePoll) GetVoter() string { + if m != nil { + return m.Voter + } + return "" +} + +func (m *VotePoll) GetOptions() Options { + if m != nil { + return m.Options + } + return Options{} +} + +func (m *VotePoll) GetMetadata() []byte { + if m != nil { + return m.Metadata + } + return nil +} + +func (m *VotePoll) GetSubmittedAt() types.Timestamp { + if m != nil { + return m.SubmittedAt + } + return types.Timestamp{} +} + +func init() { + proto.RegisterEnum("regen.group.v1alpha1.Choice", Choice_name, Choice_value) + proto.RegisterEnum("regen.group.v1alpha1.Proposal_Status", Proposal_Status_name, Proposal_Status_value) + proto.RegisterEnum("regen.group.v1alpha1.Proposal_Result", Proposal_Result_name, Proposal_Result_value) + proto.RegisterEnum("regen.group.v1alpha1.Proposal_ExecutorResult", Proposal_ExecutorResult_name, Proposal_ExecutorResult_value) + proto.RegisterEnum("regen.group.v1alpha1.Poll_Status", Poll_Status_name, Poll_Status_value) + proto.RegisterType((*Member)(nil), "regen.group.v1alpha1.Member") + proto.RegisterType((*Members)(nil), "regen.group.v1alpha1.Members") + proto.RegisterType((*ThresholdDecisionPolicy)(nil), "regen.group.v1alpha1.ThresholdDecisionPolicy") + proto.RegisterType((*GroupInfo)(nil), "regen.group.v1alpha1.GroupInfo") + proto.RegisterType((*GroupMember)(nil), "regen.group.v1alpha1.GroupMember") + proto.RegisterType((*GroupAccountInfo)(nil), "regen.group.v1alpha1.GroupAccountInfo") + proto.RegisterType((*Proposal)(nil), "regen.group.v1alpha1.Proposal") + proto.RegisterType((*Tally)(nil), "regen.group.v1alpha1.Tally") + proto.RegisterType((*Vote)(nil), "regen.group.v1alpha1.Vote") + proto.RegisterType((*TallyPoll)(nil), "regen.group.v1alpha1.TallyPoll") + proto.RegisterMapType((map[string]string)(nil), "regen.group.v1alpha1.TallyPoll.CountsEntry") + proto.RegisterType((*Options)(nil), "regen.group.v1alpha1.Options") + proto.RegisterType((*Poll)(nil), "regen.group.v1alpha1.Poll") + proto.RegisterType((*VotePoll)(nil), "regen.group.v1alpha1.VotePoll") +} + +func init() { proto.RegisterFile("regen/group/v1alpha1/types.proto", fileDescriptor_9b7906b115009838) } + +var fileDescriptor_9b7906b115009838 = []byte{ + // 1582 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x57, 0xcd, 0x6e, 0x1b, 0x47, + 0x12, 0xd6, 0x90, 0x14, 0x7f, 0x8a, 0x14, 0xc5, 0x6d, 0xcb, 0x16, 0x45, 0x49, 0xd4, 0x98, 0x5e, + 0xc3, 0xda, 0x35, 0x44, 0x42, 0xda, 0x5d, 0x60, 0x2d, 0xac, 0x8d, 0xa5, 0xa8, 0x91, 0x97, 0xbb, + 0xb2, 0xa8, 0x1d, 0x92, 0x4a, 0xe2, 0x43, 0x88, 0x21, 0xa7, 0x4d, 0x4d, 0x3c, 0x9c, 0x26, 0x66, + 0x9a, 0x8a, 0x99, 0x07, 0x08, 0x1c, 0x9e, 0x92, 0x53, 0x90, 0x03, 0x01, 0x03, 0x79, 0x81, 0x1c, + 0xf2, 0x00, 0x39, 0x1a, 0x39, 0x19, 0x41, 0x0e, 0x49, 0x0e, 0x41, 0x60, 0x5f, 0x72, 0xc9, 0x3b, + 0x04, 0xd3, 0xdd, 0x23, 0x72, 0x24, 0x8a, 0x72, 0x02, 0xe7, 0xa4, 0xa9, 0xee, 0xfa, 0xba, 0xab, + 0xbe, 0x2a, 0xd6, 0xd7, 0x02, 0xd9, 0xc6, 0x6d, 0x6c, 0x15, 0xda, 0x36, 0xe9, 0x75, 0x0b, 0x27, + 0x9b, 0x9a, 0xd9, 0x3d, 0xd6, 0x36, 0x0b, 0xb4, 0xdf, 0xc5, 0x4e, 0xbe, 0x6b, 0x13, 0x4a, 0xd0, + 0x02, 0xf3, 0xc8, 0x33, 0x8f, 0xbc, 0xe7, 0x91, 0x59, 0x68, 0x93, 0x36, 0x61, 0x0e, 0x05, 0xf7, + 0x8b, 0xfb, 0x66, 0xb2, 0x6d, 0x42, 0xda, 0x26, 0x2e, 0x30, 0xab, 0xd9, 0x7b, 0x54, 0xd0, 0x7b, + 0xb6, 0x46, 0x0d, 0x62, 0x89, 0xfd, 0xb5, 0xb3, 0xfb, 0xd4, 0xe8, 0x60, 0x87, 0x6a, 0x9d, 0xae, + 0x70, 0x48, 0xb4, 0x88, 0xd3, 0x21, 0xe2, 0xea, 0xcc, 0xd2, 0x59, 0x77, 0xcd, 0xea, 0xf3, 0xad, + 0xdc, 0x11, 0x84, 0x1f, 0xe0, 0x4e, 0x13, 0xdb, 0x28, 0x0d, 0x11, 0x4d, 0xd7, 0x6d, 0xec, 0x38, + 0x69, 0x49, 0x96, 0xd6, 0x63, 0xaa, 0x67, 0xa2, 0x6b, 0x10, 0x7e, 0x1f, 0x1b, 0xed, 0x63, 0x9a, + 0x0e, 0xb0, 0x0d, 0x61, 0xa1, 0x0c, 0x44, 0x3b, 0x98, 0x6a, 0xba, 0x46, 0xb5, 0x74, 0x50, 0x96, + 0xd6, 0x13, 0xea, 0xa9, 0x9d, 0xbb, 0x0f, 0x11, 0x7e, 0xae, 0x83, 0xfe, 0x05, 0x91, 0x0e, 0xff, + 0x4c, 0x4b, 0x72, 0x70, 0x3d, 0xbe, 0xb5, 0x92, 0x9f, 0x44, 0x45, 0x9e, 0xfb, 0xef, 0x84, 0x9e, + 0xff, 0xb8, 0x36, 0xa3, 0x7a, 0x90, 0xdc, 0x87, 0x12, 0x2c, 0xd6, 0x8e, 0x6d, 0xec, 0x1c, 0x13, + 0x53, 0xdf, 0xc5, 0x2d, 0xc3, 0x31, 0x88, 0x75, 0x48, 0x4c, 0xa3, 0xd5, 0x47, 0x2b, 0x10, 0xa3, + 0xde, 0x96, 0x08, 0x7a, 0xb4, 0x80, 0xee, 0x40, 0xc4, 0xa5, 0x85, 0xf4, 0x78, 0xdc, 0xf1, 0xad, + 0xa5, 0x3c, 0xe7, 0x21, 0xef, 0xf1, 0x90, 0xdf, 0x15, 0xb4, 0x7a, 0x97, 0x0a, 0xff, 0x6d, 0xf4, + 0xcd, 0x97, 0x1b, 0x49, 0xff, 0x65, 0xb9, 0x2f, 0x24, 0x88, 0xdd, 0x77, 0x23, 0x2e, 0x5b, 0x8f, + 0x08, 0x5a, 0x82, 0x28, 0x0b, 0xbf, 0x61, 0xf0, 0x9b, 0x43, 0x6a, 0x84, 0xd9, 0x65, 0x1d, 0x2d, + 0xc0, 0xac, 0xa6, 0x77, 0x0c, 0x4b, 0xb0, 0xc5, 0x8d, 0x69, 0x64, 0xb9, 0xd4, 0x9f, 0x60, 0xdb, + 0xbd, 0x2b, 0x1d, 0xe2, 0x67, 0x09, 0x13, 0x5d, 0x87, 0x04, 0x25, 0x54, 0x33, 0x1b, 0xa2, 0x00, + 0xb3, 0xec, 0xc8, 0x38, 0x5b, 0x7b, 0x8b, 0x57, 0x61, 0x09, 0xa2, 0x4d, 0xd3, 0x69, 0x10, 0xcb, + 0xec, 0xa7, 0xc3, 0xb2, 0xb4, 0x1e, 0x55, 0x23, 0x4d, 0xd3, 0xa9, 0x58, 0x66, 0x3f, 0xf7, 0x2e, + 0xc4, 0x59, 0xc4, 0xa2, 0xc2, 0x53, 0x62, 0xfe, 0x3b, 0x84, 0x39, 0xe1, 0x82, 0xaa, 0xa9, 0x25, + 0x52, 0x85, 0x6f, 0xee, 0xd3, 0x00, 0xa4, 0xd8, 0x05, 0xc5, 0x56, 0x8b, 0xf4, 0x2c, 0xca, 0x98, + 0xb9, 0xb8, 0x8f, 0xc6, 0xef, 0x0f, 0x5c, 0xc0, 0x59, 0xf0, 0x22, 0xce, 0x42, 0x17, 0x73, 0x36, + 0xeb, 0xe7, 0xec, 0xff, 0x30, 0xaf, 0x8b, 0xd2, 0x35, 0xba, 0xac, 0x76, 0x8c, 0x97, 0xf8, 0xd6, + 0xc2, 0xb9, 0xfa, 0x17, 0xad, 0xfe, 0x0e, 0xfa, 0xfa, 0x5c, 0xad, 0xd5, 0xa4, 0xee, 0x6f, 0xb4, + 0x9b, 0x90, 0xd4, 0xb1, 0x6d, 0x9c, 0xb0, 0x66, 0x69, 0x3c, 0xc6, 0xfd, 0x74, 0x84, 0x85, 0x33, + 0x37, 0x5a, 0xfd, 0x1f, 0xee, 0x6f, 0x47, 0x9f, 0x3e, 0x5b, 0x9b, 0xf9, 0xf9, 0xd9, 0x9a, 0x94, + 0xfb, 0x05, 0x20, 0x7a, 0x68, 0x93, 0x2e, 0x71, 0x34, 0x13, 0xad, 0x41, 0xbc, 0x2b, 0xbe, 0x47, + 0xd4, 0x83, 0xb7, 0x54, 0xd6, 0xc7, 0x29, 0x0b, 0xf8, 0x29, 0x9b, 0xd6, 0x35, 0x2b, 0x10, 0xe3, + 0x67, 0xb8, 0xbf, 0xac, 0x90, 0x1c, 0x74, 0xbb, 0xff, 0x74, 0x01, 0x95, 0x20, 0xe1, 0xf4, 0x9a, + 0x1d, 0x83, 0x52, 0xac, 0x37, 0x34, 0xde, 0x39, 0xf1, 0xad, 0xcc, 0x39, 0x0a, 0x6a, 0xde, 0xe4, + 0x10, 0xbf, 0x81, 0xf8, 0x29, 0xaa, 0x48, 0xd1, 0x0d, 0x98, 0xe3, 0x15, 0xf3, 0xa8, 0x0e, 0xb3, + 0xd8, 0x13, 0x6c, 0xf1, 0x48, 0xf0, 0xbd, 0x05, 0x57, 0xb9, 0x93, 0xc6, 0xbb, 0xe0, 0xd4, 0x39, + 0xc2, 0x9c, 0xaf, 0xb4, 0xc7, 0x3a, 0xc4, 0xc3, 0xdc, 0x85, 0xb0, 0x43, 0x35, 0xda, 0x73, 0xd2, + 0x51, 0x59, 0x5a, 0x4f, 0x6e, 0xdd, 0x9c, 0xdc, 0x6f, 0x1e, 0x85, 0xf9, 0x2a, 0x73, 0x56, 0x05, + 0xc8, 0x85, 0xdb, 0xd8, 0xe9, 0x99, 0x34, 0x1d, 0x7b, 0x2d, 0xb8, 0xca, 0x9c, 0x55, 0x01, 0x42, + 0xff, 0x06, 0x38, 0x21, 0x14, 0x37, 0xdc, 0xd3, 0x70, 0x1a, 0x18, 0x33, 0xcb, 0x93, 0x8f, 0xa8, + 0x69, 0xa6, 0xd9, 0x17, 0xd4, 0xc4, 0x5c, 0x90, 0x1b, 0x09, 0x46, 0xdb, 0xa3, 0xd9, 0x12, 0x7f, + 0x4d, 0x62, 0x3d, 0x00, 0x3a, 0x82, 0x79, 0xfc, 0x04, 0xb7, 0x7a, 0x94, 0xd8, 0x0d, 0x91, 0x45, + 0x82, 0x65, 0xb1, 0x71, 0x49, 0x16, 0x8a, 0x40, 0x89, 0x6c, 0x92, 0xd8, 0x67, 0xa3, 0x75, 0x08, + 0x75, 0x9c, 0xb6, 0x93, 0x9e, 0x63, 0x43, 0x76, 0x62, 0xb3, 0xab, 0xcc, 0x23, 0xf7, 0x42, 0x82, + 0x30, 0x67, 0x14, 0x6d, 0x02, 0xaa, 0xd6, 0x8a, 0xb5, 0x7a, 0xb5, 0x51, 0x3f, 0xa8, 0x1e, 0x2a, + 0xa5, 0xf2, 0x5e, 0x59, 0xd9, 0x4d, 0xcd, 0x64, 0x96, 0x06, 0x43, 0xf9, 0xaa, 0x77, 0x33, 0xf7, + 0x2d, 0x5b, 0x27, 0x9a, 0x69, 0xe8, 0x68, 0x13, 0x52, 0x02, 0x52, 0xad, 0xef, 0x3c, 0x28, 0xd7, + 0x6a, 0xca, 0x6e, 0x4a, 0xca, 0x2c, 0x0f, 0x86, 0xf2, 0xa2, 0x1f, 0x50, 0xf5, 0x3a, 0x09, 0xdd, + 0x86, 0x39, 0x01, 0x29, 0xed, 0x57, 0xaa, 0xca, 0x6e, 0x2a, 0x90, 0x49, 0x0f, 0x86, 0xf2, 0x82, + 0xdf, 0xbf, 0x64, 0x12, 0x07, 0xeb, 0x68, 0x03, 0x92, 0xc2, 0xb9, 0xb8, 0x53, 0x51, 0xdd, 0xd3, + 0x83, 0x93, 0xc2, 0x29, 0x36, 0x89, 0x4d, 0xb1, 0x9e, 0x09, 0x3d, 0xfd, 0x3c, 0x3b, 0x93, 0xfb, + 0x41, 0x82, 0xb0, 0xe0, 0x61, 0x13, 0x90, 0xaa, 0x54, 0xeb, 0xfb, 0xb5, 0x69, 0x29, 0x71, 0x5f, + 0x2f, 0xa5, 0x7f, 0x8c, 0x41, 0xf6, 0xca, 0x07, 0xc5, 0xfd, 0xf2, 0x43, 0x96, 0xd4, 0xea, 0x60, + 0x28, 0x2f, 0xf9, 0x21, 0x75, 0xeb, 0x91, 0x61, 0x69, 0xa6, 0xf1, 0x01, 0xd6, 0x51, 0x01, 0xe6, + 0x05, 0xac, 0x58, 0x2a, 0x29, 0x87, 0x35, 0x96, 0x58, 0x66, 0x30, 0x94, 0xaf, 0xf9, 0x31, 0xc5, + 0x56, 0x0b, 0x77, 0xa9, 0x0f, 0xa0, 0x2a, 0xff, 0x55, 0x4a, 0x3c, 0xb7, 0x09, 0x00, 0x15, 0xbf, + 0x87, 0x5b, 0xa3, 0xe4, 0x3e, 0x0b, 0x40, 0xd2, 0x5f, 0x7c, 0xb4, 0x03, 0xcb, 0xca, 0xdb, 0x4a, + 0xa9, 0x5e, 0xab, 0xa8, 0x8d, 0x89, 0xd9, 0x5e, 0x1f, 0x0c, 0xe5, 0x55, 0xef, 0x54, 0x3f, 0xd8, + 0xcb, 0xfa, 0x2e, 0x2c, 0x9e, 0x3d, 0xe3, 0xa0, 0x52, 0x6b, 0xa8, 0xf5, 0x83, 0x94, 0x94, 0x91, + 0x07, 0x43, 0x79, 0x65, 0x32, 0xfe, 0x80, 0x50, 0xb5, 0x67, 0xa1, 0x7b, 0xe7, 0xe1, 0xd5, 0x7a, + 0xa9, 0xa4, 0x54, 0xab, 0xa9, 0xc0, 0xb4, 0xeb, 0xab, 0xbd, 0x56, 0xcb, 0x9d, 0x6d, 0x13, 0xf0, + 0x7b, 0xc5, 0xf2, 0x7e, 0x5d, 0x55, 0x52, 0xc1, 0x69, 0xf8, 0x3d, 0xcd, 0x30, 0x7b, 0x36, 0xe6, + 0xdc, 0x6c, 0x87, 0xdc, 0x99, 0x9b, 0xfb, 0x48, 0x82, 0x59, 0xf6, 0x53, 0x45, 0xcb, 0x10, 0xeb, + 0x63, 0xa7, 0xc1, 0xa6, 0x8d, 0x10, 0xa0, 0x68, 0x1f, 0x3b, 0x25, 0xd7, 0x76, 0x15, 0xc8, 0x22, + 0x62, 0x4f, 0x4c, 0x5a, 0x8b, 0xf0, 0xad, 0x1b, 0x30, 0xa7, 0x35, 0x1d, 0xaa, 0x19, 0x96, 0xd8, + 0xe7, 0x4a, 0x94, 0x10, 0x8b, 0xdc, 0x69, 0x15, 0xe0, 0x04, 0x53, 0xef, 0x84, 0x10, 0x7f, 0x71, + 0xb8, 0x2b, 0x6c, 0x5b, 0xc4, 0xf2, 0xad, 0x04, 0xa1, 0x23, 0x42, 0xf1, 0xe5, 0x73, 0x7f, 0x01, + 0x66, 0xdd, 0x91, 0x62, 0x7b, 0x2f, 0x05, 0x66, 0xb8, 0x5a, 0xdc, 0x3a, 0x26, 0x46, 0x0b, 0xb3, + 0x10, 0x92, 0x17, 0x69, 0x71, 0x89, 0xf9, 0xa8, 0xc2, 0x77, 0xaa, 0x56, 0xbe, 0x09, 0x2d, 0xc8, + 0x7d, 0x22, 0x41, 0x8c, 0x51, 0x7c, 0x48, 0x4c, 0x13, 0x95, 0x20, 0xcc, 0x48, 0xf0, 0xde, 0x74, + 0xb7, 0xa7, 0x8c, 0x4f, 0x17, 0x90, 0x67, 0x0c, 0x39, 0x8a, 0x45, 0xed, 0xbe, 0x2a, 0xa0, 0x99, + 0x3b, 0x10, 0x1f, 0x5b, 0x46, 0x29, 0x08, 0xba, 0xd2, 0xca, 0x8b, 0xe6, 0x7e, 0x32, 0x82, 0x34, + 0xb3, 0x87, 0x4f, 0x09, 0x72, 0x8d, 0xed, 0xc0, 0x3f, 0x25, 0x41, 0xf5, 0x2d, 0x88, 0x54, 0xba, + 0xae, 0xfa, 0xb2, 0x47, 0x2a, 0x35, 0xa8, 0x89, 0x79, 0x40, 0x31, 0x55, 0x58, 0x5e, 0x4d, 0x66, + 0x21, 0xc4, 0xe2, 0x5e, 0x84, 0x48, 0x97, 0x98, 0x63, 0xf5, 0x08, 0xbb, 0x66, 0x59, 0xbf, 0xe4, + 0x71, 0xc2, 0x0e, 0xf3, 0x1e, 0x27, 0xcc, 0x40, 0x77, 0x21, 0x42, 0xf8, 0xdd, 0x8c, 0xef, 0xf8, + 0xd6, 0xea, 0x64, 0x0a, 0x44, 0x80, 0x9e, 0x0a, 0x08, 0x8c, 0xab, 0xf9, 0x2d, 0x1b, 0x6b, 0x94, + 0xd8, 0xe2, 0x51, 0xe7, 0x99, 0xac, 0xc9, 0x5c, 0x75, 0x32, 0x8d, 0x8e, 0x41, 0x99, 0xe2, 0xce, + 0x72, 0xe9, 0xd9, 0x77, 0x17, 0xd0, 0xae, 0x4f, 0xbc, 0x22, 0xec, 0xea, 0xb5, 0x4b, 0xd8, 0x3f, + 0x2f, 0x60, 0xe3, 0xed, 0x12, 0xbd, 0xa4, 0x5d, 0x62, 0x6f, 0xe4, 0xe9, 0x00, 0x13, 0x9e, 0x0e, + 0x77, 0x4e, 0x9f, 0x01, 0x71, 0xd6, 0xea, 0xd7, 0x2f, 0x50, 0x40, 0xb7, 0x81, 0xce, 0x3c, 0x01, + 0xc6, 0x14, 0x38, 0xf1, 0x1b, 0x15, 0x38, 0xf7, 0xd5, 0x48, 0xff, 0x36, 0x2e, 0xd0, 0xbf, 0xab, + 0x83, 0xa1, 0xfc, 0x27, 0xf7, 0x5e, 0xbf, 0xf6, 0x6d, 0x4c, 0xd4, 0xbe, 0xc5, 0xc1, 0x50, 0xbe, + 0x32, 0x72, 0x1e, 0xe9, 0xde, 0xad, 0xf3, 0xba, 0xb7, 0x30, 0x18, 0xca, 0xa9, 0x91, 0xaf, 0xd0, + 0xbc, 0xbf, 0x4c, 0xd0, 0xbc, 0x33, 0x21, 0xf8, 0xf4, 0x4e, 0xb4, 0xf5, 0xf7, 0x12, 0x44, 0xdd, + 0x51, 0x33, 0xbd, 0xb5, 0x27, 0x8f, 0x99, 0xb1, 0xfe, 0x0d, 0xfe, 0x8e, 0xfe, 0xfd, 0xa3, 0xe7, + 0xcd, 0x5f, 0x75, 0x08, 0xf3, 0x11, 0x87, 0xae, 0x01, 0x2a, 0xfd, 0xa7, 0x52, 0x2e, 0x29, 0xfe, + 0x1a, 0xa1, 0x39, 0x88, 0x89, 0xf5, 0x83, 0x4a, 0x4a, 0x42, 0x49, 0x00, 0x61, 0xbe, 0xa3, 0x54, + 0x53, 0x01, 0x84, 0x20, 0x29, 0xec, 0xe2, 0x4e, 0xb5, 0x56, 0x2c, 0x1f, 0xa4, 0x82, 0x68, 0x1e, + 0xe2, 0x62, 0xed, 0x48, 0xa9, 0x55, 0x52, 0xa1, 0x9d, 0x7b, 0xcf, 0x5f, 0x66, 0xa5, 0x17, 0x2f, + 0xb3, 0xd2, 0x4f, 0x2f, 0xb3, 0xd2, 0xc7, 0xaf, 0xb2, 0x33, 0x2f, 0x5e, 0x65, 0x67, 0xbe, 0x7b, + 0x95, 0x9d, 0x79, 0xf8, 0xe7, 0xb6, 0x41, 0x8f, 0x7b, 0xcd, 0x7c, 0x8b, 0x74, 0x0a, 0xfc, 0xbf, + 0x69, 0xf1, 0x67, 0xc3, 0xd1, 0x1f, 0x17, 0x9e, 0xf0, 0x7f, 0xf5, 0x9b, 0x61, 0x96, 0xcc, 0xdf, + 0x7e, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xd4, 0xd7, 0x89, 0x57, 0x00, 0x10, 0x00, 0x00, +} + +func (this *GroupAccountInfo) Equal(that interface{}) bool { + if that == nil { + return this == nil + } + + that1, ok := that.(*GroupAccountInfo) + if !ok { + that2, ok := that.(GroupAccountInfo) + if ok { + that1 = &that2 + } else { + return false + } + } + if that1 == nil { + return this == nil + } else if this == nil { + return false + } + if this.Address != that1.Address { + return false + } + if this.GroupId != that1.GroupId { + return false + } + if this.Admin != that1.Admin { + return false + } + if !bytes.Equal(this.Metadata, that1.Metadata) { + return false + } + if this.Version != that1.Version { + return false + } + if !this.DecisionPolicy.Equal(that1.DecisionPolicy) { + return false + } + if !bytes.Equal(this.DerivationKey, that1.DerivationKey) { + return false + } + return true +} +func (m *Member) 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 *Member) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Member) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if len(m.Weight) > 0 { + i -= len(m.Weight) + copy(dAtA[i:], m.Weight) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Weight))) + i-- + dAtA[i] = 0x12 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Members) 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 *Members) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Members) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Members) > 0 { + for iNdEx := len(m.Members) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Members[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ThresholdDecisionPolicy) 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 *ThresholdDecisionPolicy) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ThresholdDecisionPolicy) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Timeout.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if len(m.Threshold) > 0 { + i -= len(m.Threshold) + copy(dAtA[i:], m.Threshold) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Threshold))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GroupInfo) 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 *GroupInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GroupInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BlsOnly { + i-- + if m.BlsOnly { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x30 + } + if len(m.TotalWeight) > 0 { + i -= len(m.TotalWeight) + copy(dAtA[i:], m.TotalWeight) + i = encodeVarintTypes(dAtA, i, uint64(len(m.TotalWeight))) + i-- + dAtA[i] = 0x2a + } + if m.Version != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x20 + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GroupMember) 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 *GroupMember) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GroupMember) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Member != nil { + { + size, err := m.Member.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if m.GroupId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *GroupAccountInfo) 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 *GroupAccountInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GroupAccountInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.DerivationKey) > 0 { + i -= len(m.DerivationKey) + copy(dAtA[i:], m.DerivationKey) + i = encodeVarintTypes(dAtA, i, uint64(len(m.DerivationKey))) + i-- + dAtA[i] = 0x3a + } + if m.DecisionPolicy != nil { + { + size, err := m.DecisionPolicy.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + if m.Version != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Version)) + i-- + dAtA[i] = 0x28 + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x22 + } + if len(m.Admin) > 0 { + i -= len(m.Admin) + copy(dAtA[i:], m.Admin) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Admin))) + i-- + dAtA[i] = 0x1a + } + if m.GroupId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Proposal) 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 *Proposal) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Proposal) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Msgs) > 0 { + for iNdEx := len(m.Msgs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Msgs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + } + if m.ExecutorResult != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.ExecutorResult)) + i-- + dAtA[i] = 0x60 + } + { + size, err := m.Timeout.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x5a + { + size, err := m.VoteState.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x52 + if m.Result != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Result)) + i-- + dAtA[i] = 0x48 + } + if m.Status != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x40 + } + if m.GroupAccountVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupAccountVersion)) + i-- + dAtA[i] = 0x38 + } + if m.GroupVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupVersion)) + i-- + dAtA[i] = 0x30 + } + { + size, err := m.SubmittedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.Proposers) > 0 { + for iNdEx := len(m.Proposers) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Proposers[iNdEx]) + copy(dAtA[i:], m.Proposers[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Proposers[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x1a + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *Tally) 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 *Tally) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Tally) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.VetoCount) > 0 { + i -= len(m.VetoCount) + copy(dAtA[i:], m.VetoCount) + i = encodeVarintTypes(dAtA, i, uint64(len(m.VetoCount))) + i-- + dAtA[i] = 0x22 + } + if len(m.AbstainCount) > 0 { + i -= len(m.AbstainCount) + copy(dAtA[i:], m.AbstainCount) + i = encodeVarintTypes(dAtA, i, uint64(len(m.AbstainCount))) + i-- + dAtA[i] = 0x1a + } + if len(m.NoCount) > 0 { + i -= len(m.NoCount) + copy(dAtA[i:], m.NoCount) + i = encodeVarintTypes(dAtA, i, uint64(len(m.NoCount))) + i-- + dAtA[i] = 0x12 + } + if len(m.YesCount) > 0 { + i -= len(m.YesCount) + copy(dAtA[i:], m.YesCount) + i = encodeVarintTypes(dAtA, i, uint64(len(m.YesCount))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Vote) 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 *Vote) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Vote) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.SubmittedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x22 + } + if m.Choice != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Choice)) + i-- + dAtA[i] = 0x18 + } + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.ProposalId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.ProposalId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *TallyPoll) 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 *TallyPoll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *TallyPoll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Counts) > 0 { + for k := range m.Counts { + v := m.Counts[k] + baseI := i + i -= len(v) + copy(dAtA[i:], v) + i = encodeVarintTypes(dAtA, i, uint64(len(v))) + i-- + dAtA[i] = 0x12 + i -= len(k) + copy(dAtA[i:], k) + i = encodeVarintTypes(dAtA, i, uint64(len(k))) + i-- + dAtA[i] = 0xa + i = encodeVarintTypes(dAtA, i, uint64(baseI-i)) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Options) 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 *Options) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Options) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Titles) > 0 { + for iNdEx := len(m.Titles) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Titles[iNdEx]) + copy(dAtA[i:], m.Titles[iNdEx]) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Titles[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *Poll) 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 *Poll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Poll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Timeout.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + if m.Status != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x58 + } + if m.GroupVersion != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupVersion)) + i-- + dAtA[i] = 0x50 + } + { + size, err := m.SubmittedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4a + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x42 + } + { + size, err := m.VoteState.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x3a + if m.VoteLimit != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.VoteLimit)) + i-- + dAtA[i] = 0x30 + } + if len(m.Creator) > 0 { + i -= len(m.Creator) + copy(dAtA[i:], m.Creator) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Creator))) + i-- + dAtA[i] = 0x2a + } + { + size, err := m.Options.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + if len(m.Title) > 0 { + i -= len(m.Title) + copy(dAtA[i:], m.Title) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Title))) + i-- + dAtA[i] = 0x1a + } + if m.GroupId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.GroupId)) + i-- + dAtA[i] = 0x10 + } + if m.PollId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *VotePoll) 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 *VotePoll) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *VotePoll) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.SubmittedAt.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x2a + if len(m.Metadata) > 0 { + i -= len(m.Metadata) + copy(dAtA[i:], m.Metadata) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Metadata))) + i-- + dAtA[i] = 0x22 + } + { + size, err := m.Options.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTypes(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Voter) > 0 { + i -= len(m.Voter) + copy(dAtA[i:], m.Voter) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Voter))) + i-- + dAtA[i] = 0x12 + } + if m.PollId != 0 { + i = encodeVarintTypes(dAtA, i, uint64(m.PollId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { + offset -= sovTypes(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Member) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Weight) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Members) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Members) > 0 { + for _, e := range m.Members { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *ThresholdDecisionPolicy) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Threshold) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Timeout.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *GroupInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovTypes(uint64(m.GroupId)) + } + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Version != 0 { + n += 1 + sovTypes(uint64(m.Version)) + } + l = len(m.TotalWeight) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.BlsOnly { + n += 2 + } + return n +} + +func (m *GroupMember) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.GroupId != 0 { + n += 1 + sovTypes(uint64(m.GroupId)) + } + if m.Member != nil { + l = m.Member.Size() + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *GroupAccountInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.GroupId != 0 { + n += 1 + sovTypes(uint64(m.GroupId)) + } + l = len(m.Admin) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Version != 0 { + n += 1 + sovTypes(uint64(m.Version)) + } + if m.DecisionPolicy != nil { + l = m.DecisionPolicy.Size() + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.DerivationKey) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Proposal) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTypes(uint64(m.ProposalId)) + } + l = len(m.Address) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if len(m.Proposers) > 0 { + for _, s := range m.Proposers { + l = len(s) + n += 1 + l + sovTypes(uint64(l)) + } + } + l = m.SubmittedAt.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.GroupVersion != 0 { + n += 1 + sovTypes(uint64(m.GroupVersion)) + } + if m.GroupAccountVersion != 0 { + n += 1 + sovTypes(uint64(m.GroupAccountVersion)) + } + if m.Status != 0 { + n += 1 + sovTypes(uint64(m.Status)) + } + if m.Result != 0 { + n += 1 + sovTypes(uint64(m.Result)) + } + l = m.VoteState.Size() + n += 1 + l + sovTypes(uint64(l)) + l = m.Timeout.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.ExecutorResult != 0 { + n += 1 + sovTypes(uint64(m.ExecutorResult)) + } + if len(m.Msgs) > 0 { + for _, e := range m.Msgs { + l = e.Size() + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *Tally) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.YesCount) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.NoCount) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.AbstainCount) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.VetoCount) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + +func (m *Vote) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ProposalId != 0 { + n += 1 + sovTypes(uint64(m.ProposalId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.Choice != 0 { + n += 1 + sovTypes(uint64(m.Choice)) + } + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.SubmittedAt.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *TallyPoll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Counts) > 0 { + for k, v := range m.Counts { + _ = k + _ = v + mapEntrySize := 1 + len(k) + sovTypes(uint64(len(k))) + 1 + len(v) + sovTypes(uint64(len(v))) + n += mapEntrySize + 1 + sovTypes(uint64(mapEntrySize)) + } + } + return n +} + +func (m *Options) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Titles) > 0 { + for _, s := range m.Titles { + l = len(s) + n += 1 + l + sovTypes(uint64(l)) + } + } + return n +} + +func (m *Poll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovTypes(uint64(m.PollId)) + } + if m.GroupId != 0 { + n += 1 + sovTypes(uint64(m.GroupId)) + } + l = len(m.Title) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Options.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Creator) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + if m.VoteLimit != 0 { + n += 1 + sovTypes(uint64(m.VoteLimit)) + } + l = m.VoteState.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.SubmittedAt.Size() + n += 1 + l + sovTypes(uint64(l)) + if m.GroupVersion != 0 { + n += 1 + sovTypes(uint64(m.GroupVersion)) + } + if m.Status != 0 { + n += 1 + sovTypes(uint64(m.Status)) + } + l = m.Timeout.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func (m *VotePoll) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PollId != 0 { + n += 1 + sovTypes(uint64(m.PollId)) + } + l = len(m.Voter) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.Options.Size() + n += 1 + l + sovTypes(uint64(l)) + l = len(m.Metadata) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = m.SubmittedAt.Size() + n += 1 + l + sovTypes(uint64(l)) + return n +} + +func sovTypes(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTypes(x uint64) (n int) { + return sovTypes(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Member) 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 ErrIntOverflowTypes + } + 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: Member: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Member: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Weight = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Members) 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 ErrIntOverflowTypes + } + 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: Members: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Members: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Members", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Members = append(m.Members, Member{}) + if err := m.Members[len(m.Members)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ThresholdDecisionPolicy) 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 ErrIntOverflowTypes + } + 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: ThresholdDecisionPolicy: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ThresholdDecisionPolicy: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Threshold", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Threshold = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timeout", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Timeout.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GroupInfo) 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 ErrIntOverflowTypes + } + 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: GroupInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GroupInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TotalWeight", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TotalWeight = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field BlsOnly", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.BlsOnly = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GroupMember) 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 ErrIntOverflowTypes + } + 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: GroupMember: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GroupMember: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Member", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Member == nil { + m.Member = &Member{} + } + if err := m.Member.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GroupAccountInfo) 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 ErrIntOverflowTypes + } + 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: GroupAccountInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GroupAccountInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Admin", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Admin = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DecisionPolicy", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DecisionPolicy == nil { + m.DecisionPolicy = &types1.Any{} + } + if err := m.DecisionPolicy.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DerivationKey", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DerivationKey = append(m.DerivationKey[:0], dAtA[iNdEx:postIndex]...) + if m.DerivationKey == nil { + m.DerivationKey = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Proposal) 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 ErrIntOverflowTypes + } + 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: Proposal: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Proposal: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proposers", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proposers = append(m.Proposers, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubmittedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SubmittedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupVersion", wireType) + } + m.GroupVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupAccountVersion", wireType) + } + m.GroupAccountVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupAccountVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 8: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= Proposal_Status(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 9: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Result", wireType) + } + m.Result = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Result |= Proposal_Result(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteState", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VoteState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timeout", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Timeout.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ExecutorResult", wireType) + } + m.ExecutorResult = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ExecutorResult |= Proposal_ExecutorResult(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Msgs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Msgs = append(m.Msgs, &types1.Any{}) + if err := m.Msgs[len(m.Msgs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Tally) 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 ErrIntOverflowTypes + } + 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: Tally: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Tally: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field YesCount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.YesCount = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NoCount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NoCount = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AbstainCount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AbstainCount = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VetoCount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.VetoCount = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Vote) 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 ErrIntOverflowTypes + } + 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: Vote: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Vote: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ProposalId", wireType) + } + m.ProposalId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ProposalId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Choice", wireType) + } + m.Choice = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Choice |= Choice(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubmittedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SubmittedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *TallyPoll) 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 ErrIntOverflowTypes + } + 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: TallyPoll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: TallyPoll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Counts", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Counts == nil { + m.Counts = make(map[string]string) + } + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey < 0 { + return ErrInvalidLengthTypes + } + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue < 0 { + return ErrInvalidLengthTypes + } + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + m.Counts[mapkey] = mapvalue + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Options) 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 ErrIntOverflowTypes + } + 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: Options: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Options: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Titles", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Titles = append(m.Titles, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *Poll) 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 ErrIntOverflowTypes + } + 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: Poll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Poll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupId", wireType) + } + m.GroupId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Title", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Title = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Creator", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Creator = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteLimit", wireType) + } + m.VoteLimit = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.VoteLimit |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field VoteState", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.VoteState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubmittedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SubmittedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 10: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field GroupVersion", wireType) + } + m.GroupVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.GroupVersion |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 11: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= Poll_Status(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timeout", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Timeout.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VotePoll) 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 ErrIntOverflowTypes + } + 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: VotePoll: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VotePoll: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PollId", wireType) + } + m.PollId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PollId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Voter", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Voter = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Options", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Options.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Metadata", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Metadata = append(m.Metadata[:0], dAtA[iNdEx:postIndex]...) + if m.Metadata == nil { + m.Metadata = []byte{} + } + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubmittedAt", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.SubmittedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTypes(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTypes + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTypes + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTypes + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTypes + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTypes = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTypes = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTypes = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/group/types_test.go b/x/group/types_test.go new file mode 100644 index 0000000000..c2c09e0398 --- /dev/null +++ b/x/group/types_test.go @@ -0,0 +1,967 @@ +package group + +import ( + "testing" + "time" + + "github.com/cosmos/cosmos-sdk/regen/orm" + "github.com/cosmos/cosmos-sdk/regen/types/math" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + sdk "github.com/cosmos/cosmos-sdk/types" + proto "github.com/gogo/protobuf/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestThresholdDecisionPolicy(t *testing.T) { + specs := map[string]struct { + srcPolicy ThresholdDecisionPolicy + srcTally Tally + srcTotalPower string + srcVotingDuration time.Duration + expResult DecisionPolicyResult + expErr error + }{ + "accept when yes count greater than threshold": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "2"}, + srcTotalPower: "3", + srcVotingDuration: time.Millisecond, + expResult: DecisionPolicyResult{Allow: true, Final: true}, + }, + "accept when yes count equal to threshold": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "1", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + srcTotalPower: "3", + srcVotingDuration: time.Millisecond, + expResult: DecisionPolicyResult{Allow: true, Final: true}, + }, + "reject when yes count lower to threshold": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "0", NoCount: "0", AbstainCount: "0", VetoCount: "0"}, + srcTotalPower: "3", + srcVotingDuration: time.Millisecond, + expResult: DecisionPolicyResult{Allow: false, Final: false}, + }, + "reject as final when remaining votes can't cross threshold": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "2", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "0", NoCount: "2", AbstainCount: "0", VetoCount: "0"}, + srcTotalPower: "3", + srcVotingDuration: time.Millisecond, + expResult: DecisionPolicyResult{Allow: false, Final: true}, + }, + "expired when on timeout": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "2"}, + srcTotalPower: "3", + srcVotingDuration: time.Second, + expResult: DecisionPolicyResult{Allow: false, Final: true}, + }, + "expired when after timeout": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "2"}, + srcTotalPower: "3", + srcVotingDuration: time.Second + time.Nanosecond, + expResult: DecisionPolicyResult{Allow: false, Final: true}, + }, + "abstain has no impact": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "0", NoCount: "0", AbstainCount: "1", VetoCount: "0"}, + srcTotalPower: "3", + srcVotingDuration: time.Millisecond, + expResult: DecisionPolicyResult{Allow: false, Final: false}, + }, + "veto same as no": { + srcPolicy: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }, + srcTally: Tally{YesCount: "0", NoCount: "0", AbstainCount: "0", VetoCount: "2"}, + srcTotalPower: "3", + srcVotingDuration: time.Millisecond, + expResult: DecisionPolicyResult{Allow: false, Final: false}, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + res, err := spec.srcPolicy.Allow(spec.srcTally, spec.srcTotalPower, spec.srcVotingDuration) + if spec.expErr != nil { + require.Error(t, err) + return + } + require.NoError(t, err) + assert.Equal(t, spec.expResult, res) + }) + } +} + +func TestThresholdDecisionPolicyValidate(t *testing.T) { + specs := map[string]struct { + src ThresholdDecisionPolicy + expErr bool + }{ + "all good": {src: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }}, + "greater than group total weight": { + src: ThresholdDecisionPolicy{ + Threshold: "2", + Timeout: proto.Duration{Seconds: 1}, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.Validate(GroupInfo{TotalWeight: "1"}) + assert.Equal(t, spec.expErr, err != nil, err) + }) + } +} + +func TestThresholdDecisionPolicyValidateBasic(t *testing.T) { + maxSeconds := int64(10000 * 365.25 * 24 * 60 * 60) + specs := map[string]struct { + src ThresholdDecisionPolicy + expErr bool + }{ + "all good": {src: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: 1}, + }}, + "threshold missing": {src: ThresholdDecisionPolicy{ + Timeout: proto.Duration{Seconds: 1}, + }, + expErr: true, + }, + "timeout missing": {src: ThresholdDecisionPolicy{ + Threshold: "1", + }, + expErr: true, + }, + "duration out of limit": {src: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: maxSeconds + 1}, + }, + expErr: true, + }, + "no negative thresholds": {src: ThresholdDecisionPolicy{ + Threshold: "-1", + Timeout: proto.Duration{Seconds: 1}, + }, + expErr: true, + }, + "no empty thresholds": {src: ThresholdDecisionPolicy{ + Timeout: proto.Duration{Seconds: 1}, + }, + expErr: true, + }, + "no zero thresholds": {src: ThresholdDecisionPolicy{ + Timeout: proto.Duration{Seconds: 1}, + Threshold: "0", + }, + expErr: true, + }, + "no negative timeouts": {src: ThresholdDecisionPolicy{ + Threshold: "1", + Timeout: proto.Duration{Seconds: -1}, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + assert.Equal(t, spec.expErr, err != nil, err) + }) + } +} + +func TestVotePrimaryKey(t *testing.T) { + addr := []byte{0xff, 0xfe} + v := Vote{ + ProposalId: 1, + Voter: string(addr[:]), + } + assert.Equal(t, []byte{0, 0, 0, 0, 0, 0, 0, 1, 0xff, 0xfe, 0}, orm.PrimaryKey(&v)) +} + +func TestGroupInfoValidation(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + adminAddr := addr.String() + + specs := map[string]struct { + src GroupInfo + expErr bool + }{ + "all good": { + src: GroupInfo{ + GroupId: 1, + Admin: adminAddr, + Metadata: nil, + Version: 1, + TotalWeight: "0", + }, + }, + "invalid group": { + src: GroupInfo{ + Admin: adminAddr, + Metadata: nil, + Version: 1, + TotalWeight: "0", + }, + expErr: true, + }, + "invalid admin": { + src: GroupInfo{ + GroupId: 1, + Admin: "", + Metadata: nil, + Version: 1, + TotalWeight: "0", + }, + expErr: true, + }, + "invalid version": { + src: GroupInfo{ + GroupId: 1, + Admin: adminAddr, + Metadata: nil, + TotalWeight: "0", + }, + expErr: true, + }, + "unset total weight": { + src: GroupInfo{ + GroupId: 1, + Admin: adminAddr, + Metadata: nil, + Version: 1, + }, + expErr: true, + }, + "negative total weight": { + src: GroupInfo{ + GroupId: 1, + Admin: adminAddr, + Metadata: nil, + Version: 1, + TotalWeight: "-1", + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestGroupMemberValidation(t *testing.T) { + _, _, addr := testdata.KeyTestPubAddr() + memberAddr := addr.String() + + specs := map[string]struct { + src GroupMember + expErr bool + }{ + "all good": { + src: GroupMember{ + GroupId: 1, + Member: &Member{ + Address: memberAddr, + Weight: "1", + Metadata: nil, + }, + }, + }, + "invalid group": { + src: GroupMember{ + GroupId: 0, + Member: &Member{ + Address: memberAddr, + Weight: "1", + Metadata: nil, + }, + }, + expErr: true, + }, + "invalid address": { + src: GroupMember{ + GroupId: 1, + Member: &Member{ + Address: "invalid-member-address", + Weight: "1", + Metadata: nil, + }, + }, + expErr: true, + }, + "empty address": { + src: GroupMember{ + GroupId: 1, + Member: &Member{ + Weight: "1", + Metadata: nil, + }, + }, + expErr: true, + }, + "invalid weight": { + src: GroupMember{ + GroupId: 1, + Member: &Member{ + Address: memberAddr, + Weight: "-1", + Metadata: nil, + }, + }, + expErr: true, + }, + "nil weight": { + src: GroupMember{ + GroupId: 1, + Member: &Member{ + Address: memberAddr, + Metadata: nil, + }, + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestGroupAccountInfo(t *testing.T) { + specs := map[string]struct { + groupAccount sdk.AccAddress + group uint64 + admin sdk.AccAddress + version uint64 + threshold string + timeout proto.Duration + derivationKey []byte + expErr bool + }{ + "all good": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + derivationKey: []byte("derivationKey"), + timeout: proto.Duration{Seconds: 1}, + }, + "invalid group": { + group: 0, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "valid variable length group account address": { + group: 1, + groupAccount: []byte("any-group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: false, + }, + "empty group account address": { + group: 1, + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "empty admin account address": { + group: 1, + groupAccount: []byte("valid--group-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "valid variable length admin account address": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("any-admin-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: false, + }, + "empty version number": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "missing decision policy": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "missing decision policy timeout": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "decision policy with invalid timeout": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: -1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "missing decision policy threshold": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "decision policy with negative threshold": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "-1", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "decision policy with zero threshold": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "0", + timeout: proto.Duration{Seconds: 1}, + derivationKey: []byte("derivationKey"), + expErr: true, + }, + "empty derivationKey": { + group: 1, + groupAccount: []byte("valid--group-address"), + admin: []byte("valid--admin-address"), + version: 1, + threshold: "1", + timeout: proto.Duration{Seconds: 1}, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + m, err := NewGroupAccountInfo( + spec.groupAccount, + spec.group, + spec.admin, + nil, + spec.version, + &ThresholdDecisionPolicy{ + Threshold: spec.threshold, + Timeout: spec.timeout, + }, + spec.derivationKey, + ) + require.NoError(t, err) + + if spec.expErr { + require.Error(t, m.ValidateBasic()) + } else { + require.NoError(t, m.ValidateBasic()) + } + }) + } +} + +func TestTallyValidateBasic(t *testing.T) { + specs := map[string]struct { + src Tally + expErr bool + }{ + "all good": { + src: Tally{ + YesCount: "1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + }, + "negative yes count": { + src: Tally{ + YesCount: "-1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expErr: true, + }, + "negative no count": { + src: Tally{ + YesCount: "0", + NoCount: "-1", + AbstainCount: "0", + VetoCount: "0", + }, + expErr: true, + }, + "negative abstain count": { + src: Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "-1", + VetoCount: "0", + }, + expErr: true, + }, + "negative veto count": { + src: Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "-1", + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestTallyTotalCounts(t *testing.T) { + specs := map[string]struct { + src Tally + expErr bool + res string + }{ + "all good": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + res: "4", + }, + "negative yes count": { + src: Tally{ + YesCount: "-1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expErr: true, + }, + "negative no count": { + src: Tally{ + YesCount: "0", + NoCount: "-1", + AbstainCount: "0", + VetoCount: "0", + }, + expErr: true, + }, + "negative abstain count": { + src: Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "-1", + VetoCount: "0", + }, + expErr: true, + }, + "negative veto count": { + src: Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "-1", + }, + expErr: true, + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + res, err := spec.src.TotalCounts() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, spec.res, math.DecimalString(res)) + } + }) + } +} + +func TestTallyAdd(t *testing.T) { + specs := map[string]struct { + src Tally + expTally Tally + vote Vote + expErr bool + weight string + }{ + "add yes": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "5", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + vote: Vote{Choice: Choice_CHOICE_YES}, + weight: "4", + }, + "add no": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "1", + NoCount: "2.5", + AbstainCount: "1", + VetoCount: "1", + }, + vote: Vote{Choice: Choice_CHOICE_NO}, + weight: "1.5", + }, + "add abstain": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "2.5", + VetoCount: "1", + }, + vote: Vote{Choice: Choice_CHOICE_ABSTAIN}, + weight: "1.5", + }, + "add veto": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "2.5", + }, + vote: Vote{Choice: Choice_CHOICE_VETO}, + weight: "1.5", + }, + "negative yes count": { + src: Tally{ + YesCount: "-1", + NoCount: "0", + AbstainCount: "0", + VetoCount: "0", + }, + expErr: true, + weight: "4", + }, + "negative no count": { + src: Tally{ + YesCount: "0", + NoCount: "-1", + AbstainCount: "0", + VetoCount: "0", + }, + expErr: true, + weight: "4", + }, + "negative abstain count": { + src: Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "-1", + VetoCount: "0", + }, + expErr: true, + weight: "4", + }, + "negative veto count": { + src: Tally{ + YesCount: "0", + NoCount: "0", + AbstainCount: "0", + VetoCount: "-1", + }, + expErr: true, + weight: "4", + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.Add(spec.vote, spec.weight) + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, spec.expTally.YesCount, spec.src.YesCount) + require.Equal(t, spec.expTally.NoCount, spec.src.NoCount) + require.Equal(t, spec.expTally.AbstainCount, spec.src.AbstainCount) + require.Equal(t, spec.expTally.VetoCount, spec.src.VetoCount) + } + }) + } +} + +func TestTallySub(t *testing.T) { + specs := map[string]struct { + src Tally + expTally Tally + vote Vote + expErr bool + weight string + }{ + "sub yes": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "0.5", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + vote: Vote{Choice: Choice_CHOICE_YES}, + weight: "0.5", + }, + "sub no": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "1", + NoCount: "0.5", + AbstainCount: "1", + VetoCount: "1", + }, + vote: Vote{Choice: Choice_CHOICE_NO}, + weight: "0.5", + }, + "sub abstain": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "0.5", + VetoCount: "1", + }, + vote: Vote{Choice: Choice_CHOICE_ABSTAIN}, + weight: "0.5", + }, + "sub veto": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expTally: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "0.5", + }, + vote: Vote{Choice: Choice_CHOICE_VETO}, + weight: "0.5", + }, + "negative yes count": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expErr: true, + vote: Vote{Choice: Choice_CHOICE_YES}, + weight: "2", + }, + "negative no count": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expErr: true, + vote: Vote{Choice: Choice_CHOICE_NO}, + weight: "2", + }, + "negative abstain count": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expErr: true, + vote: Vote{Choice: Choice_CHOICE_ABSTAIN}, + weight: "2", + }, + "negative veto count": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expErr: true, + vote: Vote{Choice: Choice_CHOICE_VETO}, + weight: "2", + }, + "unknown choice": { + src: Tally{ + YesCount: "1", + NoCount: "1", + AbstainCount: "1", + VetoCount: "1", + }, + expErr: true, + vote: Vote{Choice: Choice_CHOICE_UNSPECIFIED}, + weight: "2", + }, + } + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.Sub(spec.vote, spec.weight) + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, spec.expTally.YesCount, spec.src.YesCount) + require.Equal(t, spec.expTally.NoCount, spec.src.NoCount) + require.Equal(t, spec.expTally.AbstainCount, spec.src.AbstainCount) + require.Equal(t, spec.expTally.VetoCount, spec.src.VetoCount) + } + }) + } +} + +func TestAccAddressesValidateBasic(t *testing.T) { + _, _, addr1 := testdata.KeyTestPubAddr() + _, _, addr2 := testdata.KeyTestPubAddr() + specs := map[string]struct { + src AccAddresses + expErr bool + }{ + "valid": { + src: AccAddresses{addr1, addr2}, + expErr: false, + }, + "same address twice": { + src: AccAddresses{addr1, addr1}, + expErr: true, + }, + } + + for msg, spec := range specs { + t.Run(msg, func(t *testing.T) { + err := spec.src.ValidateBasic() + if spec.expErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/x/group/typesupport.go b/x/group/typesupport.go new file mode 100644 index 0000000000..7d827cc730 --- /dev/null +++ b/x/group/typesupport.go @@ -0,0 +1,65 @@ +package group + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +func (ms Members) ValidateBasic() error { + index := make(map[string]struct{}, len(ms.Members)) + for i := range ms.Members { + member := ms.Members[i] + if err := member.ValidateBasic(); err != nil { + return err + } + addr := member.Address + if _, exists := index[addr]; exists { + return sdkerrors.Wrapf(ErrDuplicate, "address: %s", addr) + } + index[addr] = struct{}{} + } + return nil +} + +type AccAddresses []sdk.AccAddress + +// ValidateBasic verifies that there's no duplicate address. +// Individual account address validation has to be done separately. +func (a AccAddresses) ValidateBasic() error { + index := make(map[string]struct{}, len(a)) + for i := range a { + accAddr := a[i] + addr := string(accAddr) + if _, exists := index[addr]; exists { + return sdkerrors.Wrapf(ErrDuplicate, "address: %s", accAddr.String()) + } + index[addr] = struct{}{} + } + return nil +} + +// ValidateBasic verifies that check the length of options and if there is any duplication. +func (ops Options) ValidateBasic() error { + if len(ops.Titles) == 0 { + return sdkerrors.Wrap(ErrEmpty, "poll options") + } + + for i, x := range ops.Titles { + if len(x) == 0 { + return sdkerrors.Wrapf(ErrEmpty, "option %d", i) + } + } + + if err := assertOptionsLength(ops, "options"); err != nil { + return err + } + + index := make(map[string]struct{}, len(ops.Titles)) + for _, x := range ops.Titles { + if _, exists := index[x]; exists { + return sdkerrors.Wrapf(ErrDuplicate, "option %s", x) + } + index[x] = struct{}{} + } + return nil +} \ No newline at end of file